I'm using Bulma for my recent projects. Really like the framework! One feature that would be really helpful is a 'spacing' helper. See e.g. https://github.com/inuitcss/inuitcss/blob/develop/utilities/_utilities.spacings.scss
With this option, you can easily add a padding or margin to specific elements like:
.u-margin-top {}
.u-padding-left-large {}
.u-margin-right-small {}
.u-padding {}
.u-padding-right-none {}
.u-padding-horizontal {}
.u-padding-vertical-small {}
Perhaps we can also include the breakpoints into it, like the current 'responsive helpers'. That way we can e.g. set no padding on mobile devices and a top padding on desktops.
If others think this might be a useful addition, I can create a pull request to incorporate this feature.
I have this on my latest project. Here is my code:
$sizes: (0,10,15,20,25,30,50);
$positions: ('top','left','bottom','right');
@each $size in $sizes {
.u-m-#{$size} {
margin: $size + px;
}
.u-p-#{$size} {
padding: $size + px;
}
}
You would use it like this
<div class="m-t-10">This div has top margin 10px</div>
You can add a scaling factor and scale it each size.
This is an interesting idea but I don't want to bloat Bulma with helpers, as you basically end up designing with HTML, which I'm not a fan of.
@jgthms Spacing utility is my most like feature in Twitter Bootstrap, do you think the spacing feature would bloat Bulma?
I hope basic-spacing feature would be implemented in Bulma future release.
Following @ilicmarko's comment, here's my spacing.scss file…
$sizeUnit: rem;
$marginKey: 'm';
$paddingKey: 'p';
$separator: '-';
$sizes: (
('none', 0),
('xxs', 0.125),
('xs', 0.25),
('sm', 0.5),
('md', 1),
('lg', 2),
('xl', 4),
('xxl', 8),
);
$positions: (
('t', 'top'),
('r', 'right'),
('b', 'bottom'),
('l', 'left')
);
@function sizeValue($key, $value) {
@return if($key == 'none', 0, $value + $sizeUnit);
}
@each $size in $sizes {
$sizeKey: nth($size, 1);
$sizeValue: nth($size, 2);
.#{$marginKey}#{$separator}#{$sizeKey} {
margin: sizeValue($sizeKey, $sizeValue);
}
.#{$paddingKey}#{$separator}#{$sizeKey} {
padding: sizeValue($sizeKey, $sizeValue);
}
@each $position in $positions {
$posKey: nth($position, 1);
$posValue: nth($position, 2);
.#{$marginKey}#{$separator}#{$posKey}#{$separator}#{$sizeKey} {
margin-#{$posValue}: sizeValue($sizeKey, $sizeValue);
}
.#{$paddingKey}#{$separator}#{$posKey}#{$separator}#{$sizeKey} {
padding-#{$posValue}: sizeValue($sizeKey, $sizeValue);
}
}
}
…which generates the following classes…
.m-none { margin: 0; }
.p-none { padding: 0; }
.m-t-none { margin-top: 0; }
.p-t-none { padding-top: 0; }
.m-r-none { margin-right: 0; }
.p-r-none { padding-right: 0; }
.m-b-none { margin-bottom: 0; }
.p-b-none { padding-bottom: 0; }
.m-l-none { margin-left: 0; }
.p-l-none { padding-left: 0; }
.m-xxs { margin: 0.125rem; }
.p-xxs { padding: 0.125rem; }
.m-t-xxs { margin-top: 0.125rem; }
.p-t-xxs { padding-top: 0.125rem; }
.m-r-xxs { margin-right: 0.125rem; }
.p-r-xxs { padding-right: 0.125rem; }
.m-b-xxs { margin-bottom: 0.125rem; }
.p-b-xxs { padding-bottom: 0.125rem; }
.m-l-xxs { margin-left: 0.125rem; }
.p-l-xxs { padding-left: 0.125rem; }
.m-xs { margin: 0.25rem; }
.p-xs { padding: 0.25rem; }
.m-t-xs { margin-top: 0.25rem; }
.p-t-xs { padding-top: 0.25rem; }
.m-r-xs { margin-right: 0.25rem; }
.p-r-xs { padding-right: 0.25rem; }
.m-b-xs { margin-bottom: 0.25rem; }
.p-b-xs { padding-bottom: 0.25rem; }
.m-l-xs { margin-left: 0.25rem; }
.p-l-xs { padding-left: 0.25rem; }
.m-sm { margin: 0.5rem; }
.p-sm { padding: 0.5rem; }
.m-t-sm { margin-top: 0.5rem; }
.p-t-sm { padding-top: 0.5rem; }
.m-r-sm { margin-right: 0.5rem; }
.p-r-sm { padding-right: 0.5rem; }
.m-b-sm { margin-bottom: 0.5rem; }
.p-b-sm { padding-bottom: 0.5rem; }
.m-l-sm { margin-left: 0.5rem; }
.p-l-sm { padding-left: 0.5rem; }
.m-md { margin: 1rem; }
.p-md { padding: 1rem; }
.m-t-md { margin-top: 1rem; }
.p-t-md { padding-top: 1rem; }
.m-r-md { margin-right: 1rem; }
.p-r-md { padding-right: 1rem; }
.m-b-md { margin-bottom: 1rem; }
.p-b-md { padding-bottom: 1rem; }
.m-l-md { margin-left: 1rem; }
.p-l-md { padding-left: 1rem; }
.m-lg { margin: 2rem; }
.p-lg { padding: 2rem; }
.m-t-lg { margin-top: 2rem; }
.p-t-lg { padding-top: 2rem; }
.m-r-lg { margin-right: 2rem; }
.p-r-lg { padding-right: 2rem; }
.m-b-lg { margin-bottom: 2rem; }
.p-b-lg { padding-bottom: 2rem; }
.m-l-lg { margin-left: 2rem; }
.p-l-lg { padding-left: 2rem; }
.m-xl { margin: 4rem; }
.p-xl { padding: 4rem; }
.m-t-xl { margin-top: 4rem; }
.p-t-xl { padding-top: 4rem; }
.m-r-xl { margin-right: 4rem; }
.p-r-xl { padding-right: 4rem; }
.m-b-xl { margin-bottom: 4rem; }
.p-b-xl { padding-bottom: 4rem; }
.m-l-xl { margin-left: 4rem; }
.p-l-xl { padding-left: 4rem; }
.m-xxl { margin: 8rem; }
.p-xxl { padding: 8rem; }
.m-t-xxl { margin-top: 8rem; }
.p-t-xxl { padding-top: 8rem; }
.m-r-xxl { margin-right: 8rem; }
.p-r-xxl { padding-right: 8rem; }
.m-b-xxl { margin-bottom: 8rem; }
.p-b-xxl { padding-bottom: 8rem; }
.m-l-xxl { margin-left: 8rem; }
.p-l-xxl { padding-left: 8rem; }
…and is configurable by changing the values of $sizeUnit (rem, em, px), $marginKey ('m', 'marg', 'margin', etc), $paddingKey ('p', 'pad', 'padding', etc), $separator ('-', '_', '' for none, etc) and $sizes (whatever keys/values you need).
👍
@furey In according to the structure of bulma we should use it like that:
$marginKey: 'has-margin';
$paddingKey: 'has-padding';
$positions: (
('top', 'top'),
('right', 'right'),
('bottom', 'bottom'),
('left', 'left')
);
Anyway. Thanks for the snipped :)
I think I would be against this. While these helpers are useful sometimes it's not something I feel is essential. Maybe as an extension or something?
In some projects, I have created helpers like 'no-padding-left' etc. But I find if I do change the padding/margin. I just override it in the CSS file. 99% of the time I have a class styling the component to suit the brand and so would change the padding/margin there as well. I don't see the point in having the helpers when you're adding CSS anyway.
When it comes to keeping the code DRY, it's practically impossible in CSS/HTML. You either repeat properties or you repeat class names. Both of which will gzip nicely, and I would rather repeat in the CSS keeping my HTML clean as this is most likely where I will mainly be adding/changing code.
If this was a CSS utility library without the component structure Bulma has, then I would say go ahead.
Maybe @furey it needs:
...
margin-#{$posValue}: sizeValue($sizeKey, $sizeValue) !important;
...
padding-#{$posValue}: sizeValue($sizeKey, $sizeValue) !important;
...
The !important part?
here is one also
$spaceamounts: (0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100); // Adjust this to include the pixel amounts you need.
$sides: (top, bottom, left, right); // Leave this variable alone
@each $space in $spaceamounts {
@each $side in $sides {
.m-#{str-slice($side, 0, 1)}-#{$space} {
margin-#{$side}: #{$space}px !important;
}
.p-#{str-slice($side, 0, 1)}-#{$space} {
padding-#{$side}: #{$space}px !important;
}
}
}
Other prior art:
Personally I like the selectors from mrmrs/css-spacing: short selectors, REMs and vertical/ horizontal as well as each side. @furey's is close save for lack of both-vertical/ horizontal in on selector e.g. pvxl, mhs etc. Honestly I wouldn't mind pulling in a seperate utility class except I haven't found one in SASS/SCSS that does this well.
Edit: I took @furey's loop as a starting point, tweaked a few variables and added support for all veritical and horizontal to give you .mas, .pvxl, etc. Gist: https://gist.github.com/thom-nic/d873616fb448913e58ce34bd3c24c921
@jgthms I think spacing helpers are very essential, I use them in every bootstrap project, It's the only disappointing thing in Bulma, hope you consider that.
@furey thanks for the snippet its great, variable sizes gets in conflict with bulma framework.
Best.
@furey Thanks for the snippet.
With my setup I changed the $sizes variable to $customSizes because it conflicts with the Bulma sizes variables which is named the same.
I also added this snippet inside the each loop to generate classes for just top and bottom padding/margins.
.#{$marginKey}#{$separator}#{tb}#{$separator}#{$sizeKey} {
margin: sizeValue($sizeKey, $sizeValue) 0;
}
.#{$paddingKey}#{$separator}#{tb}#{$separator}#{$sizeKey} {
padding: sizeValue($sizeKey, $sizeValue) 0;
}
@jgthms That is a very hypocritical stance to take especially since this WHOLE library is about designing with HTML.
This strong attitude(thought) is bad for bulma!. Not listening to community is almost main reason of any product dying. You've been warned!
I love this product and I'm missing spacing feature a lot. Hope you will listen us.
I agree, listen to community specially if the request is logical as in this case. I read all the documentation before deciding to search for answer online, because the site I made looks horrible due to spacing issues. I think a pad class is required
If a bloatware like spacing helpers is this essential bulma is a wrong framework for you. Use bootstrap instead.
@hubbyist Really...down voting all comments...
Are you really web developer? I checked your page. It looks you are a backend cum frontend developer.
Bulma is component based. I hope you're aware of that. User can easily pick what's required and actually they should use custom build for production.
Got it?
Each official component add a maintenance cost on a framework and spacing helpers are a way of adding exceptions to any general layout thus defeating the purpose of a css framework, so I do not think they deserve that much attention.
@hubbyist what would you suggest as an alternative to adding spacing to the framework? Would you rather one create one's own margin/padding classes and add media queries to set spacing throughout the project?
I just do not see a meaning full difference between <section style="padding-left: 0"></section> and <section class="padding-left-zero"></section>.
Aren't inline styles considered bad practice and of relatively worse performance compared to CSS classes?
If there is a single property in a global css class it is part of the "site content" rather than "layout and design" in my opinion. So must be inside the data not in css classes to be cleaned in later code and content iterations. Or stay inline forever for content to be portable if this is an integral part of the meaning.
Well, spacing in a typical website would be all over the place really, and not a single occurrence, so I disagree; but that's alright, I just wanted to know your opinion. Thank you 🙂
I am changing my stance on this. I am in favor of keeping bulma bloat-free so i agree with the author
Joining the hot discussion, here are some thoughts.
As @hubbyist I also find that writing <div class="m-t-2"></div> is not the right way to write components as this is 0% reusable.
I'm surprised Bootstrap added it, I have been using v3.x for quite some time and as far as I know it wasn't there.
The only thing I was missing then, was horizontal spacing, to isolate sections. I ended up writing <hr class="invisible" />. This was not perfect since it was extra html, but somehow this could be considered semantically correct, since it was to isolate sections between each other, which <hr /> are for, and this one happened to be styled transparent.
Anyway, Bulma has <div class="section"></div> which does this. One can play with variable if it is too big or too small.
But IMHO, for any other case, the rule must be styled at the component level, within (S)CSS. Yes it is a pain, but this is because it is an exception from the original component, and going away from the framework's component is more work, one needs to be aware of this. Either buy the standard, or pay more.
Eventually in prototyping situations, where cleanliness comes after speed, class="m-t-1" could make sense, but then copy-paste @furey's above code in a specific file, and start it with the following comment: // TODO: remove this file as soon as no longer necessary as this produces cheap, unresponsive, unDRY code. This has nothing to do in the core framework.
As a final word, I'd say that there might be specific situations where spacing is not correctly handled by the framework. Then, one should create an issue regarding this specific situation, and eventually there will be a fix or a utility for this case, but that's it.
Thanks for reading, I am very opened to critics. :smile:
So, obv littering your markup with <div class='m-t-2'> is lazy. This is how I use spacing helpers:
.myRowButton // hypothetical, yes there are other ways to do this.
@extend .m-r-xs, .button
&:last-child
@extend .m-r-z // this is, arguably, the least-useful of all spacing helpers, but still.
.saveBtnInline
@extend .myRowBtn, .success
.cancelBtnInline
@extend .myRowBtn, .warning
section
&.main
@extends .m-v-l
&.news
@extends .m-v-m, .p-a-m
As with most "helpers" the best way is to extend them with into own style definitions. And as your site grows, if you want to tweak spacing/ padding, it's as easy as tweaking the the helper variable. Or at least changing some -ls to -ms.
The problems you're solving is down the road you don't have to grep for margin.*px, dealing with not consistent use of px vs em vs rem or .2rem here but oops .3rem there.
Edit: I'll add that at this point, I don't care about this particular issue since it seems apparent it's not going anywhere. I'm using the helper I posted in my previous comment and moved on from this.
In my experience most devs will already have their own collection of homebrew/borrowed framework-independent helpers that they prefer to use in all their projects.
That's not an argument against adding some of them to Bulma, but given the author's limited time I would rather see him focus on Bulma's core components.
I create a gist based on @furey's code including margin auto: https://gist.github.com/VictorOtavio/e0576b755a49ef3682354091c6911dcb
@VictorOtavio what do you think about creating a Github project with this?
If a spacing system was introduced, it should be as versatile and useful as Bootstrap's which incorporates responsive breakpoints - Bulma's version could reference mobile, desktop, widescreen:
.mb-is-mobile-1 (margin-bottom: 0.5 rem)
.mb-is-mobile-2 (margin-bottom: 0.75 rem)
.mb-is-mobile-3 (margin-bottom: 1 rem)
...
.mb-is-tablet-1 (margin-bottom: 0.5 rem)
.mb-is-tablet-2 (margin-bottom: 0.75 rem)
.mb-is-tablet-3 (margin-bottom: 1 rem)
...
etc.
I include the following helper code in my styles
// Spacing helpers
@each $size in [0,1,2,3,4,5] {
@each $pos in ['top','right','bottom','left'] {
.margin-#{$pos}-#{$size} {
margin-#{$pos}: $size + rem
}
.padding-#{$pos}-#{$size} {
padding-#{$pos}: $size + rem
}
}
}
after which I can add rules like the following to space out elements:
// Add 1rem vertical space between buttons
.button + .button {
@extend .margin-top-1;
}
I agree that adding spacers in your markup makes it look very messy fast and is also in my opinion an anti-pattern. Space is between elements, and shouldn't be directly assigned to one of them without regard of their siblings.
I've put together a modified version from Bootstrap which incorporates the .tablet, .desktop etc. breakpoints: ( I added a mobile breakpoint - personal preference )
$spacer: 1rem !default;
$spacers: () !default;
$spacers: map-merge((
0: 0,
1: ($spacer * .25),
2: ($spacer * .5),
3: $spacer,
4: ($spacer * 1.5),
5: ($spacer * 3)
), $spacers);
$grid-breakpoints: (
xs: 0,
mobile: 576px,
tablet: $tablet,
desktop: $desktop,
widescreen: $widescreen,
hd: $fullhd
) !default;
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
$min: map-get($breakpoints, $name);
@return if($min != 0, $min, null);
}
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($name, $breakpoints);
@if $min {
@media (min-width: $min) {
@content;
}
} @else {
@content;
}
}
@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
@return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
}
@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {
$n: index($breakpoint-names, $name);
@return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);
}
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
@each $prop, $abbrev in (margin: m, padding: p) {
@each $size, $length in $spacers {
.is-#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; }
.is-#{$abbrev}t#{$infix}-#{$size},
.is-#{$abbrev}y#{$infix}-#{$size} {
#{$prop}-top: $length !important;
}
.is-#{$abbrev}r#{$infix}-#{$size},
.is-#{$abbrev}x#{$infix}-#{$size} {
#{$prop}-right: $length !important;
}
.is-#{$abbrev}b#{$infix}-#{$size},
.is-#{$abbrev}y#{$infix}-#{$size} {
#{$prop}-bottom: $length !important;
}
.is-#{$abbrev}l#{$infix}-#{$size},
.is-#{$abbrev}x#{$infix}-#{$size} {
#{$prop}-left: $length !important;
}
}
}
// Some special margin utils
.is-m#{$infix}-auto { margin: auto !important; }
.is-mt#{$infix}-auto,
.is-my#{$infix}-auto {
margin-top: auto !important;
}
.is-mr#{$infix}-auto,
.is-mx#{$infix}-auto {
margin-right: auto !important;
}
.is-mb#{$infix}-auto,
.is-my#{$infix}-auto {
margin-bottom: auto !important;
}
.is-ml#{$infix}-auto,
.is-mx#{$infix}-auto {
margin-left: auto !important;
}
}
}
https://gist.github.com/wrabit/47767c82a7b62f4fe0d931b94a9b489b
@jgthms Has your thinking on adding spacing helpers changed at all? Being able to have a consistent spacing scale that I can apply just by adding classnames like mt-tablet-3 would be a huge productivity win for me.
I love Bulma as much as the next person, but I'm not gonna lie, not having these is pretty disappointing.
Moving from bootstrap to bulma, without this and a whole lot of other responsive helpers, my productivity slowed. Of course we could write these rules out but its tedious and think the overhead of having such helpers natively included is worth it. Im copying the scss rules from bootstrap for display, text align, float and spacing, checkout my gist for spacing.
@williamabbott, I'm quite interested to know why people move from Bootstrap to Bulma, yet still expecting to have everything from Bootstrap available. The question simply comes forward - why not stay with Bootstrap?
I don't have a specific opinion on this but certainly dislike having a trillion different spacing options. I'm working on an application which is now 100% non-reusable simply due to dozen different ways developers used spacing to lay out controls on the page using Bootstrap helpers. I really see no difference in writing style elements to move things around, compared to that. But, as I've said, I have no specific opinion and would prefer someone who's been studying UX a bit harder to come up with some conventions.
I also think that adding a separate scss file with modifiers (as demonstrated several times above) is a great solution as it is specific to each project and/or section.
@MisterY I wasn't aware this was a trend that people are expecting everything from BS to be here? My case might differ slightly as I am mainly talking about 'responsive' spacer / helpers. I use them in BS to build optimal layouts across all devices, without even thinking too hard about it. This is a valuable time saver for me and honestly think, for someone who already covers a wide area of the stack, this little feature goes a long way. Is it really too hard to imagine why people move? Joining a new team, contributing to multiple projects and in my case using Buefy Vuejs component library because I needed their components, but it used Bulma. Individuals arrive from their own journey of using x, y, z tools that they become efficient using, of course if they find value in them, they're going to want them everywhere they go.
This Bulma helpers project looks pretty good: https://github.com/jmaczan/bulma-helpers
I'd love to see helpers become an official part of Bulma, but barring that, maybe the next best thing is we rally behind this project and help improve it (although it seems pretty complete).
really hope utility classes can be added lol
This Bulma helpers project is working very well for me. I've only used it for
<section class="has-margin-top-15">... but that's awesome right there. I agree with someone above that it's very nice to stick to the patterns of the bulma naming conventions, and one can rest assured that has-padding-right-20 will add 20px padding to the right.
Have a look and see if this is worth our collective investments of time and thought.
Helpers on margin and padding are especially useful when they can be mixed with responsiveness, like "is-tablet mleft-4" for example;
But since developers thoughts are really closed about this, I suggest people to go back on Bootstrap for the next project, as someone else suggested and as I did. Don't pick the wrong framework just to try something different, if the one you're using is good anyways. Good luck.
What is the difference between spacing helpers and the already included typography size helpers (is-size-1..7)? Don't both fundamentally make you design with HTML instead of CSS? If so, why do we have one and not the other?
@marqpdx the bulma-helpers minified css is 313kb.
**On second thought - I've read some opinions - I get it now.
Here is an alternative version that includes Bootstrap responsive classes like mt-lg-3, mx-xl-1, etc.
https://www.sassmeister.com/gist/11d8724693331b957089b3e342f45f49
https://gist.github.com/sbefort/11d8724693331b957089b3e342f45f49
Thanks Shaun - this will be really helpful!
On Mon, Apr 8, 2019 at 7:34 AM Shaun Befort notifications@github.com
wrote:
Here is an alternative version that includes Bootstrap responsive classes
like mt-lg-3, mx-xl-1, etc.https://www.sassmeister.com/gist/11d8724693331b957089b3e342f45f49
https://gist.github.com/sbefort/11d8724693331b957089b3e342f45f49—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/jgthms/bulma/issues/451#issuecomment-480689667, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AIZAlpktfWiR6aS39mUxQY1do7xEKWEAks5vetTLgaJpZM4Leqso
.
Thank you @sbefort
My version:
$sizes: (0,10,15,20,25,30,50);
$positions: ('top','left','bottom','right');
@each $size in $sizes {
@each $position in $positions {
.m#{str-slice($position, 0, 1)}-#{$size} {
margin-#{$position}: $size + px;
}
.p#{str-slice($position, 0, 1)}-#{$size} {
padding-#{$position}: $size + px;
}
}
}
Then you could use it like this:
<div class="mt-10">This div has top margin 10px</div>
I really liked @truongnmt 's simple solution, but I wanted to have something similar to Tailwindcss since I'm using that on a different project, so I modified their example slightly and added a couple extras (negative margins, margin auto):
/* Add Tailwindcss-ish margin and padding helpers */
$sizes:
0 0,
1 0.25,
2 0.5,
3 0.75,
4 1,
5 1.25,
6 1.5,
8 2,
10 2.5,
12 3,
16 4,
20 5,
24 6,
32 8,
40 10,
48 12,
56 14,
64 16;
$positions: ('top','left','bottom','right');
@each $index, $size in $sizes {
@each $position in $positions {
.m#{str-slice($position, 0, 1)}-#{$index} {
margin-#{$position}: $size + rem;
}
.p#{str-slice($position, 0, 1)}-#{$index} {
padding-#{$position}: $size + rem;
}
.-m#{str-slice($position, 0, 1)}-#{$index} {
margin-#{$position}: -$size + rem;
}
}
}
.m-auto {
margin: auto;
}
.mx-auto {
margin-left: auto;
margin-right: auto;
}
A few thoughts. I came here because I needed to add vertical spacing between sections of a complex form.
First of all, quotes like this:
This strong attitude(thought) is bad for bulma!. Not listening to community is almost main reason of any product dying. You've been warned!
...are highly disrespectful. Comments like these are the reason why open source maintainers are fed up with their projects and overly demanding (non-paying) user base. If a project starts adding everything that the community demands, it usually ends up as a bloated collection of incoherent components. I'm not saying that spacing helpers are such a thing, but it is the project leaders' decision what they want to integrate into the core and what they don't want. If they think it doesn't fit in the core, then add it to projects like "bulma-helpers" or the "helpers" directory of your own project.
In my experience, good open source projects stay good over the years due to the features they reject, not due to the features they add.
Now to the spacing itself: If we start adding classes like "mt-10" for 10 px top margin, then where is the difference to setting style="margin-top: 10px;"? If there should be a set of spacing helpers, it should be abstract, so that it can be adjusted and scaled depending on the project and the responsive environment. A system with indicators like "space-top-(s|m|l|xl)" or a number based system similar to the "is-size-(1..7)" is much more useful. I want to influence the vertical "rhythm" of my page elements, but I want that rhythm to feel consistent on all pages. Absolute pixel sizes in class names do not achieve that goal.
But in the end, if I want to style sections of my page in a consistent style specific to my page, then that's exactly what classes + CSS are made for. There's nothing bad about adding class="form-section" to my form sections and then adding a .form-section { ... } block in my project CSS file.
Or - of course - you can include one of the many already existing spacing helpers. They're one include away.
Following @ilicmarko's comment, here's my
spacing.scssfile…$sizeUnit: rem; $marginKey: 'm'; $paddingKey: 'p'; $separator: '-'; $sizes: ( ('none', 0), ('xxs', 0.125), ('xs', 0.25), ('sm', 0.5), ('md', 1), ('lg', 2), ('xl', 4), ('xxl', 8), ); $positions: ( ('t', 'top'), ('r', 'right'), ('b', 'bottom'), ('l', 'left') ); @function sizeValue($key, $value) { @return if($key == 'none', 0, $value + $sizeUnit); } @each $size in $sizes { $sizeKey: nth($size, 1); $sizeValue: nth($size, 2); .#{$marginKey}#{$separator}#{$sizeKey} { margin: sizeValue($sizeKey, $sizeValue); } .#{$paddingKey}#{$separator}#{$sizeKey} { padding: sizeValue($sizeKey, $sizeValue); } @each $position in $positions { $posKey: nth($position, 1); $posValue: nth($position, 2); .#{$marginKey}#{$separator}#{$posKey}#{$separator}#{$sizeKey} { margin-#{$posValue}: sizeValue($sizeKey, $sizeValue); } .#{$paddingKey}#{$separator}#{$posKey}#{$separator}#{$sizeKey} { padding-#{$posValue}: sizeValue($sizeKey, $sizeValue); } } }…which generates the following classes…
.m-none { margin: 0; } .p-none { padding: 0; } .m-t-none { margin-top: 0; } .p-t-none { padding-top: 0; } .m-r-none { margin-right: 0; } .p-r-none { padding-right: 0; } .m-b-none { margin-bottom: 0; } .p-b-none { padding-bottom: 0; } .m-l-none { margin-left: 0; } .p-l-none { padding-left: 0; } .m-xxs { margin: 0.125rem; } .p-xxs { padding: 0.125rem; } .m-t-xxs { margin-top: 0.125rem; } .p-t-xxs { padding-top: 0.125rem; } .m-r-xxs { margin-right: 0.125rem; } .p-r-xxs { padding-right: 0.125rem; } .m-b-xxs { margin-bottom: 0.125rem; } .p-b-xxs { padding-bottom: 0.125rem; } .m-l-xxs { margin-left: 0.125rem; } .p-l-xxs { padding-left: 0.125rem; } .m-xs { margin: 0.25rem; } .p-xs { padding: 0.25rem; } .m-t-xs { margin-top: 0.25rem; } .p-t-xs { padding-top: 0.25rem; } .m-r-xs { margin-right: 0.25rem; } .p-r-xs { padding-right: 0.25rem; } .m-b-xs { margin-bottom: 0.25rem; } .p-b-xs { padding-bottom: 0.25rem; } .m-l-xs { margin-left: 0.25rem; } .p-l-xs { padding-left: 0.25rem; } .m-sm { margin: 0.5rem; } .p-sm { padding: 0.5rem; } .m-t-sm { margin-top: 0.5rem; } .p-t-sm { padding-top: 0.5rem; } .m-r-sm { margin-right: 0.5rem; } .p-r-sm { padding-right: 0.5rem; } .m-b-sm { margin-bottom: 0.5rem; } .p-b-sm { padding-bottom: 0.5rem; } .m-l-sm { margin-left: 0.5rem; } .p-l-sm { padding-left: 0.5rem; } .m-md { margin: 1rem; } .p-md { padding: 1rem; } .m-t-md { margin-top: 1rem; } .p-t-md { padding-top: 1rem; } .m-r-md { margin-right: 1rem; } .p-r-md { padding-right: 1rem; } .m-b-md { margin-bottom: 1rem; } .p-b-md { padding-bottom: 1rem; } .m-l-md { margin-left: 1rem; } .p-l-md { padding-left: 1rem; } .m-lg { margin: 2rem; } .p-lg { padding: 2rem; } .m-t-lg { margin-top: 2rem; } .p-t-lg { padding-top: 2rem; } .m-r-lg { margin-right: 2rem; } .p-r-lg { padding-right: 2rem; } .m-b-lg { margin-bottom: 2rem; } .p-b-lg { padding-bottom: 2rem; } .m-l-lg { margin-left: 2rem; } .p-l-lg { padding-left: 2rem; } .m-xl { margin: 4rem; } .p-xl { padding: 4rem; } .m-t-xl { margin-top: 4rem; } .p-t-xl { padding-top: 4rem; } .m-r-xl { margin-right: 4rem; } .p-r-xl { padding-right: 4rem; } .m-b-xl { margin-bottom: 4rem; } .p-b-xl { padding-bottom: 4rem; } .m-l-xl { margin-left: 4rem; } .p-l-xl { padding-left: 4rem; } .m-xxl { margin: 8rem; } .p-xxl { padding: 8rem; } .m-t-xxl { margin-top: 8rem; } .p-t-xxl { padding-top: 8rem; } .m-r-xxl { margin-right: 8rem; } .p-r-xxl { padding-right: 8rem; } .m-b-xxl { margin-bottom: 8rem; } .p-b-xxl { padding-bottom: 8rem; } .m-l-xxl { margin-left: 8rem; } .p-l-xxl { padding-left: 8rem; }…and is configurable by changing the values of
$sizeUnit(rem, em, px),$marginKey('m', 'marg', 'margin', etc),$paddingKey('p', 'pad', 'padding', etc),$separator('-', '_', '' for none, etc) and$sizes(whatever keys/values you need).
I suggest to change sass variabel $size to $spacing-sizes or another name, cause sass variable $size already used by bulma.
Thanks you in advance @furey, it helps me.
Thanks, but I extend it a bit.
$sizeUnit: rem;
$marginKey: "m";
$paddingKey: "p";
$separator: "-";
$sizes: (("none", 0), ("xxs", 0.125), ("xs", 0.25), ("sm", 0.5), ("md", 1), ("lg", 2), ("xl", 4), ("xxl", 8));
$positions: (("t", "top"), ("r", "right"), ("b", "bottom"), ("l", "left"), ("x", "x"), ("y", "y"));
@function sizeValue($key, $value) {
@return if($key == "none", 0, $value + $sizeUnit);
}
@each $size in $sizes {
$sizeKey: nth($size, 1);
$sizeValue: nth($size, 2);
.#{$marginKey}#{$separator}#{$sizeKey} {
margin: sizeValue($sizeKey, $sizeValue);
}
.#{$paddingKey}#{$separator}#{$sizeKey} {
padding: sizeValue($sizeKey, $sizeValue);
}
@each $position in $positions {
$posKey: nth($position, 1);
$posValue: nth($position, 2);
.#{$marginKey}#{$separator}#{$posKey}#{$separator}#{$sizeKey} {
@if $posValue == "x" {
margin-left: sizeValue($sizeKey, $sizeValue);
margin-right: sizeValue($sizeKey, $sizeValue);
} @else if $posValue == "y" {
margin-top: sizeValue($sizeKey, $sizeValue);
margin-bottom: sizeValue($sizeKey, $sizeValue);
} @else {
margin-#{$posValue}: sizeValue($sizeKey, $sizeValue);
}
}
.#{$paddingKey}#{$separator}#{$posKey}#{$separator}#{$sizeKey} {
@if $posValue == "x" {
padding-left: sizeValue($sizeKey, $sizeValue);
padding-right: sizeValue($sizeKey, $sizeValue);
} @else if $posValue == "y" {
padding-top: sizeValue($sizeKey, $sizeValue);
padding-bottom: sizeValue($sizeKey, $sizeValue);
} @else {
padding-#{$posValue}: sizeValue($sizeKey, $sizeValue);
}
}
}
}
Also, I might remove one certain separator and tweak it a bit,
$sizeUnit: rem;
$marginKey: "m";
$paddingKey: "p";
$separator: "-";
$sizes: (("0", 0), ("xxs", 0.125), ("xs", 0.25), ("sm", 0.5), ("md", 1), ("lg", 2), ("xl", 4), ("xxl", 8));
$positions: (("t", "top"), ("r", "right"), ("b", "bottom"), ("l", "left"), ("x", "x"), ("y", "y"));
@function sizeValue($key, $value) {
@return if($key == "0", 0, $value + $sizeUnit);
}
@each $size in $sizes {
$sizeKey: nth($size, 1);
$sizeValue: nth($size, 2);
.#{$marginKey}#{$separator}#{$sizeKey} {
margin: sizeValue($sizeKey, $sizeValue);
}
.#{$paddingKey}#{$separator}#{$sizeKey} {
padding: sizeValue($sizeKey, $sizeValue);
}
@each $position in $positions {
$posKey: nth($position, 1);
$posValue: nth($position, 2);
.#{$marginKey}#{$posKey}#{$separator}#{$sizeKey} {
@if $posValue == "x" {
margin-left: sizeValue($sizeKey, $sizeValue);
margin-right: sizeValue($sizeKey, $sizeValue);
} @else if $posValue == "y" {
margin-top: sizeValue($sizeKey, $sizeValue);
margin-bottom: sizeValue($sizeKey, $sizeValue);
} @else {
margin-#{$posValue}: sizeValue($sizeKey, $sizeValue);
}
}
.#{$paddingKey}#{$posKey}#{$separator}#{$sizeKey} {
@if $posValue == "x" {
padding-left: sizeValue($sizeKey, $sizeValue);
padding-right: sizeValue($sizeKey, $sizeValue);
} @else if $posValue == "y" {
padding-top: sizeValue($sizeKey, $sizeValue);
padding-bottom: sizeValue($sizeKey, $sizeValue);
} @else {
padding-#{$posValue}: sizeValue($sizeKey, $sizeValue);
}
}
}
}
Yes spacing is needed for boosting productivity and consistency.
Yes having n classes like mrt-10 is bloatware.
So, no space helper or bloatware classes ?
With a thoughtful thinking we can get something in between for a win-win.
Based on the nomenclature of bulma alone, I would expect to have something along these lines:
(has-padding and has-margin) or (has-space)
we don't need much more than that. The margin and padding would be component-controllable and breakpointable, wait ... whaaat?
Elements/components can have an optional "library provided" value for padding/margins. (Like currently the hero component) or have the custom "provided default space" (most likely almost all elements/component will have the default one)
then developers can use it like:
<section class="my-section has-space"></section> * have default margin/padding and adjust on different breakpoints
and if needed to override, can do:
.has-space.is-desktop { ... custom spacing for dekstop breakpoints... }
.my-section.has-space { ... custom spacing for my-section element ...}
or
.my-section.has-space.is-desktop { ... custom spacing for my-section element for desktop ... }
etc... you get the idea.
For example, right now a hero component will have margin/padding unknown to the developer. So if I want to stay consistent on next section on a p to have same space on the left, I would need to:
a) figure out all the margin/padding rules for the component.
b) remove the component pad/marg and make a custom/personal one. which may break on different breakpoint and would need lots of testing.
There are block and inline elements, the has-space should only be applicable to block elements. (at least on first iteration) the idea should be to get consistent spacing on different component/pages without lots of effort.
Take a look at this example (highlighted in yellow)

the _structural padding_ is way inside in the elements and is not flowing with the structure. This is not ok. We should aim for basic/base structures that doesn't explode if we update it's content.
If the container of those anchor controller the spacing that problem would never happen, and that's great opportunity for a framework to provide us the devs the tools to avoid those kind of problems.
In my opinion of years (decades?) doing html/css, removing the padding of an a element should _not_ destroy the structure of the document

I can totally try to build a proof of concept if the authors of bulma are interested.
Spacing is an important concept when doing UX/UI. I'm not in favor of html design and bloatware classes, and that's why I also think we can greatly benefit from something well designed around it.
nevermind, this does already exist with section.
A few thoughts. I came here because I needed to add vertical spacing between sections of a complex form.
First of all, quotes like this:
This strong attitude(thought) is bad for bulma!. Not listening to community is almost main reason of any product dying. You've been warned!
...are highly disrespectful. Comments like these are the reason why open source maintainers are fed up with their projects and overly demanding (non-paying) user base. If a project starts adding everything that the community demands, it usually ends up as a bloated collection of incoherent components. I'm not saying that spacing helpers are such a thing, but it is the project leaders' decision what they want to integrate into the core and what they don't want. If they think it doesn't fit in the core, then add it to projects like "bulma-helpers" or the "helpers" directory of your own project.
In my experience, good open source projects stay good over the years due to the features they reject, not due to the features they add.
Now to the spacing itself: If we start adding classes like "mt-10" for 10 px top margin, then where is the difference to setting
style="margin-top: 10px;"? If there should be a set of spacing helpers, it should be abstract, so that it can be adjusted and scaled depending on the project and the responsive environment. A system with indicators like "space-top-(s|m|l|xl)" or a number based system similar to the "is-size-(1..7)" is much more useful. I want to influence the vertical "rhythm" of my page elements, but I want that rhythm to feel consistent on all pages. Absolute pixel sizes in class names do not achieve that goal.But in the end, if I want to style sections of my page in a consistent style specific to my page, then that's exactly what classes + CSS are made for. There's nothing bad about adding
class="form-section"to my form sections and then adding a.form-section { ... }block in my project CSS file.Or - of course - you can include one of the many already existing spacing helpers. They're one include away.
I understand what you are saying about open-source. But unless the project you're working on solves a problem that's huge in the community, you are more or less copying someone else work.
And from a developer perspective, what does Bulma solve that Bootstrap cannot solve? I would say that it has not a Jquery dependency and so you can use it with, for example, React projects; but that's kind of it, and there are very good React/Bootstrap solutions out there.
You can also choose just what you need from Bootstrap, so that you don't have very big modules around. And so on.
Personally, if I'm about to do a fast project, I may not want to use Bootstrap, but something tailored for a small project, that can be Bulma.
But without helpers, or at the first difficulties, if I have to employ external solutions because my first solution cannot solve that, I would go anyway for the big player, just because it does what I want, and I also know it.
That's my dev perspective and the reason I will probably never use Bulma. Other people may have a different opinion and that's ok. I hope the best of luck for you.
I like @truongnmt's a lot. I created a version of it that uses rem and includes .5 increments:
$sizes: (0, 1, 2, 3, 4, 5, 6, 7, 8);
$positions: ('top', 'left', 'bottom', 'right');
@each $size in $sizes {
@each $position in $positions {
.m#{str-slice($position, 0, 1)}-#{$size} {
margin-#{$position}: $size + rem;
}
.m#{str-slice($position, 0, 1)}-#{$size}5 {
margin-#{$position}: ($size + .5) + rem;
}
.p#{str-slice($position, 0, 1)}-#{$size} {
padding-#{$position}: $size + rem;
}
.p#{str-slice($position, 0, 1)}-#{$size}5 {
padding-#{$position}: ($size + .5) + rem;
}
}
}
The above produces the following CSS:
.mt-0 {margin-top: 0rem;}
.mt-05 {margin-top: 0.5rem;}
.pt-0 {padding-top: 0rem;}
.pt-05 {padding-top: 0.5rem;}
.ml-0 {margin-left: 0rem;}
.ml-05 {margin-left: 0.5rem;}
.pl-0 {padding-left: 0rem;}
.pl-05 {padding-left: 0.5rem;}
.mb-0 {margin-bottom: 0rem;}
.mb-05 {margin-bottom: 0.5rem;}
.pb-0 {padding-bottom: 0rem;}
.pb-05 {padding-bottom: 0.5rem;}
.mr-0 {margin-right: 0rem;}
.mr-05 {margin-right: 0.5rem;}
.pr-0 {padding-right: 0rem;}
.pr-05 {padding-right: 0.5rem;}
.mt-1 {margin-top: 1rem;}
.mt-15 {margin-top: 1.5rem;}
.pt-1 {padding-top: 1rem;}
.pt-15 {padding-top: 1.5rem;}
.ml-1 {margin-left: 1rem;}
.ml-15 {margin-left: 1.5rem;}
.pl-1 {padding-left: 1rem;}
.pl-15 {padding-left: 1.5rem;}
.mb-1 {margin-bottom: 1rem;}
.mb-15 {margin-bottom: 1.5rem;}
.pb-1 {padding-bottom: 1rem;}
.pb-15 {padding-bottom: 1.5rem;}
.mr-1 {margin-right: 1rem;}
.mr-15 {margin-right: 1.5rem;}
.pr-1 {padding-right: 1rem;}
.pr-15 {padding-right: 1.5rem;}
.mt-2 {margin-top: 2rem;}
.mt-25 {margin-top: 2.5rem;}
.pt-2 {padding-top: 2rem;}
.pt-25 {padding-top: 2.5rem;}
.ml-2 {margin-left: 2rem;}
.ml-25 {margin-left: 2.5rem;}
.pl-2 {padding-left: 2rem;}
.pl-25 {padding-left: 2.5rem;}
.mb-2 {margin-bottom: 2rem;}
.mb-25 {margin-bottom: 2.5rem;}
.pb-2 {padding-bottom: 2rem;}
.pb-25 {padding-bottom: 2.5rem;}
.mr-2 {margin-right: 2rem;}
.mr-25 {margin-right: 2.5rem;}
.pr-2 {padding-right: 2rem;}
.pr-25 {padding-right: 2.5rem;}
.mt-3 {margin-top: 3rem;}
.mt-35 {margin-top: 3.5rem;}
.pt-3 {padding-top: 3rem;}
.pt-35 {padding-top: 3.5rem;}
.ml-3 {margin-left: 3rem;}
.ml-35 {margin-left: 3.5rem;}
.pl-3 {padding-left: 3rem;}
.pl-35 {padding-left: 3.5rem;}
.mb-3 {margin-bottom: 3rem;}
.mb-35 {margin-bottom: 3.5rem;}
.pb-3 {padding-bottom: 3rem;}
.pb-35 {padding-bottom: 3.5rem;}
.mr-3 {margin-right: 3rem;}
.mr-35 {margin-right: 3.5rem;}
.pr-3 {padding-right: 3rem;}
.pr-35 {padding-right: 3.5rem;}
.mt-4 {margin-top: 4rem;}
.mt-45 {margin-top: 4.5rem;}
.pt-4 {padding-top: 4rem;}
.pt-45 {padding-top: 4.5rem;}
.ml-4 {margin-left: 4rem;}
.ml-45 {margin-left: 4.5rem;}
.pl-4 {padding-left: 4rem;}
.pl-45 {padding-left: 4.5rem;}
.mb-4 {margin-bottom: 4rem;}
.mb-45 {margin-bottom: 4.5rem;}
.pb-4 {padding-bottom: 4rem;}
.pb-45 {padding-bottom: 4.5rem;}
.mr-4 {margin-right: 4rem;}
.mr-45 {margin-right: 4.5rem;}
.pr-4 {padding-right: 4rem;}
.pr-45 {padding-right: 4.5rem;}
.mt-5 {margin-top: 5rem;}
.mt-55 {margin-top: 5.5rem;}
.pt-5 {padding-top: 5rem;}
.pt-55 {padding-top: 5.5rem;}
.ml-5 {margin-left: 5rem;}
.ml-55 {margin-left: 5.5rem;}
.pl-5 {padding-left: 5rem;}
.pl-55 {padding-left: 5.5rem;}
.mb-5 {margin-bottom: 5rem;}
.mb-55 {margin-bottom: 5.5rem;}
.pb-5 {padding-bottom: 5rem;}
.pb-55 {padding-bottom: 5.5rem;}
.mr-5 {margin-right: 5rem;}
.mr-55 {margin-right: 5.5rem;}
.pr-5 {padding-right: 5rem;}
.pr-55 {padding-right: 5.5rem;}
.mt-6 {margin-top: 6rem;}
.mt-65 {margin-top: 6.5rem;}
.pt-6 {padding-top: 6rem;}
.pt-65 {padding-top: 6.5rem;}
.ml-6 {margin-left: 6rem;}
.ml-65 {margin-left: 6.5rem;}
.pl-6 {padding-left: 6rem;}
.pl-65 {padding-left: 6.5rem;}
.mb-6 {margin-bottom: 6rem;}
.mb-65 {margin-bottom: 6.5rem;}
.pb-6 {padding-bottom: 6rem;}
.pb-65 {padding-bottom: 6.5rem;}
.mr-6 {margin-right: 6rem;}
.mr-65 {margin-right: 6.5rem;}
.pr-6 {padding-right: 6rem;}
.pr-65 {padding-right: 6.5rem;}
.mt-7 {margin-top: 7rem;}
.mt-75 {margin-top: 7.5rem;}
.pt-7 {padding-top: 7rem;}
.pt-75 {padding-top: 7.5rem;}
.ml-7 {margin-left: 7rem;}
.ml-75 {margin-left: 7.5rem;}
.pl-7 {padding-left: 7rem;}
.pl-75 {padding-left: 7.5rem;}
.mb-7 {margin-bottom: 7rem;}
.mb-75 {margin-bottom: 7.5rem;}
.pb-7 {padding-bottom: 7rem;}
.pb-75 {padding-bottom: 7.5rem;}
.mr-7 {margin-right: 7rem;}
.mr-75 {margin-right: 7.5rem;}
.pr-7 {padding-right: 7rem;}
.pr-75 {padding-right: 7.5rem;}
.mt-8 {margin-top: 8rem;}
.mt-85 {margin-top: 8.5rem;}
.pt-8 {padding-top: 8rem;}
.pt-85 {padding-top: 8.5rem;}
.ml-8 {margin-left: 8rem;}
.ml-85 {margin-left: 8.5rem;}
.pl-8 {padding-left: 8rem;}
.pl-85 {padding-left: 8.5rem;}
.mb-8 {margin-bottom: 8rem;}
.mb-85 {margin-bottom: 8.5rem;}
.pb-8 {padding-bottom: 8rem;}
.pb-85 {padding-bottom: 8.5rem;}
.mr-8 {margin-right: 8rem;}
.mr-85 {margin-right: 8.5rem;}
.pr-8 {padding-right: 8rem;}
.pr-85 {padding-right: 8.5rem;}
Thank all of you here for your interest and contributions. It's heartening and useful.
@dreki
Thanks for nice styles, but I realized that the styles are not responsive so it would be great to add different sizes according the Bulma breakpoints.
@jgthms How about extending the section.sass file with 2 helpers: .is-horizontal and .is-vertical, which would simply allow to remove horizontal or vertical padding?
Like
$section-padding-vertical: 3rem !default
$section-padding-horizontal: 1.5rem !default
$section-padding:$section-padding-vertical $section-padding-horizontal !default
$section-padding-medium-vertical: 9rem !default
$section-padding-medium-horizontal: $section-padding-horizontal !default
$section-padding-medium:$section-padding-medium-vertical $section-padding-medium-horizontal !default
$section-padding-large-vertical: 18rem !default
$section-padding-large-horizontal: $section-padding-horizontal !default
$section-padding-large: $section-padding-large-horizontal $section-padding-large-horizontal !default
.section
padding: $section-padding
&.is-vertical
padding: $section-padding-vertical 0
&.is-horizontal
padding: 0 $section-padding-horizontal
// Responsiveness
+desktop
// Sizes
&.is-medium
padding: $section-padding-medium
&.is-vertical
padding: $section-padding-medium-vertical 0
&.is-horizontal
padding: 0 $section-padding-medium-horizontal
&.is-large
padding: $section-padding-large
&.is-vertical
padding: $section-padding-large-vertical 0
&.is-horizontal
padding: 0 $section-padding-large-horizontal
Then one could definitely play around .section utility without having dirty custom classes.
Names could be discussed of course (eg. .horizontal-section and .vertical-section may be clearer to read).
Aren't inline styles considered bad practice and of relatively worse performance compared to CSS classes?
Actually, looking at a single rule, they're supposed to be a little faster to process, especially for older browsers, but if you start using them everywhere, you loose the benefit of reusing classes and caching CSS, so you end up with worst performance. It's also difficult to manage CSS neatly when you start to spread it all around.
For the current issue, I'm just starting using Buefy/Bulma for a lightweight project and need padding for a Vuejs component. I think I'll try mapping Bulma's $size-X values to CSS variables in my main file as global references, then I will attach a scoped style to the component for padding, referring to the global CSS variable. I'll see how far it takes me in the long run.
Re-opening. This will probably be added in the next release. I just need to figure out the best approach, as there are a few solutions shared here.
m- and p-.t top b bottom l left r right h horizontal v vertical, so mv- would be a shortcut for both margin-left and margin-rightis-small, is-normal, is-medium, is-large but they're quite long. It seems xs, sm, md, lg are preferred but it would be a new naming convention in Bulmam-0 m-1 m-2 until 6 should workm-0-mobile and m-2-tablet that could be combinedAll of this would be configurable, but having a decent default would be benefitial.
@jgthms That sounds awesome! Spacing helpers are literally the _only_ thing I immediately add to any new Bulma setup, so having it ready to go out of the box would be fabulous.
Yeah, building out some pages now and I find myself in need of some extra space!
Looking forward to what you come up with.
- Margin and padding could be abbreviated to
m-andp-.- Directions could be
ttopbbottomlleftrrighthhorizontalvvertical, somv-would be a shortcut for bothmargin-leftandmargin-right
Just to confirm, is vertical (v) example correct when you say left and right padding? I'd expect mh- be horizontal aka left/right and mv- be top/bottom.
Similar helpers as you likely know use axis, mx- and my- which make it easy to represent the directions.
If it wasn't a mistake, it _could_ make sense that you are "vertically" padding and therefore shrinking the width with left and right padding, but it'll be easily confused given the other libraries that consider vertical to be top/bottom.
I'd expect
mh-be horizontal aka left/right andmv-be top/bottom.
Yes, I got it wrong. mv is top/bottom and mh is left/right.
I second the use of mx my px py instead of mh mv ph pv
I will probably avoid mx for 2 reasons:
x is a "cross" and Flexbox already has terminology for a "cross axis", so there could be confusion as to which direction mx goes, especially since you can flip the axis in Flexbox

The x and y axis are not always horizontal and vertical respectively. If a third dimension is introduced (and there is one in CSS with the z-index), then it can look like this:

Even if mx and my can be understood as "horizontal" and "vertical", mh and mv seems more natural.
@jgthms Can that be configurable? I bounce back and forth between projects using Bulma and Tailwind every day and that would probably drive me bonkers.
@jgthms Can that be configurable
Sure. Will see what I can do.
If you enjoy to use pixels instead of ems-rems or vh-vw's, I created a package named bulma-spacing by using Bulma's naming syntax and we can merge if you want. I know ml-5 is way shorter than has-margin-left-5 but It creates consistency in application IMO. @jgthms
In spirit of bulma already using a small set of modifiers, I'd also like to see a default "handles most situations well" margin/padding on many of the containers. We can then have a small subset of spacing modifiers like is-small-space, is-medium-space, is-large-space, is-no-space, etc... we can reduce a bit of the bloat this way by having defaults that are easily modified instead of introducing a large array of spacing classes. More often than not, I only need an extra 30-60px of spacing below my elements. Another benefit of opting for this technique would be more standardized layouts. We give up a little bit of control, but it helps maintain a clean layout. Let me know your thoughts.
@zackperdue The name and amount of spacing utilities will be configurable. Here's an initial snippet:
$shortcuts: ("margin": "m", "padding": "p") !default
$directions: ("top": "t", "right": "r", "bottom": "b", "left": "l") !default
$horizontal: "x" !default
$vertical: "y" !default
$values: ("0": 0, "1": 0.25rem, "2": 0.5rem, "3": 0.75rem, "4": 1rem, "5": 1.5rem, "6": 3rem) !default
If you only wanted "small", "medium" and "large", you could customize it this way:
$values: ("small": 15px, "medium": 30px, "large": 60px)
Awesome ! Customizable helpers is definitely the best solution!
I have this on my latest project. Here is my code:
$sizes: (0,10,15,20,25,30,50); $positions: ('top','left','bottom','right'); @each $size in $sizes { .u-m-#{$size} { margin: $size + px; } .u-p-#{$size} { padding: $size + px; } }You would use it like this
<div class="m-t-10">This div has top margin 10px</div>You can add a scaling factor and scale it each size.
I think you forgot $positions in your loop.
@zackperdue The name and amount of spacing utilities will be configurable. Here's an initial snippet:
$shortcuts: ("margin": "m", "padding": "p") !default $directions: ("top": "t", "right": "r", "bottom": "b", "left": "l") !default $horizontal: "x" !default $vertical: "y" !default $values: ("0": 0, "1": 0.25rem, "2": 0.5rem, "3": 0.75rem, "4": 1rem, "5": 1.5rem, "6": 3rem) !defaultIf you only wanted "small", "medium" and "large", you could customize it this way:
$values: ("small": 15px, "medium": 30px, "large": 60px)
will horizontal and vertical be configurable too? Like if it's set to false, would it be left out of the generation? That would be great and very composable. Based on the fact that you could want only one direction and no x/y spacers.
Thank you, just jumped into this on Google. I'm hoping for the next release.
will horizontal and vertical be configurable too? Like if it's set to false, would it be left out of the generation?
Yes. You can set it to null. Here is a demonstration: https://twitter.com/jgthms/status/1260509712208015361
Building upon @ilicmarko, @furey, and @patarapolw 's comments
I love bulma and I agree that spacing classes will bloat it.
I feel that most people are used to bootstrap style spacing classes. So, I created bootstrap styled spacing helpers. I hope it helps 🙂
Here is the css:
.m-0 { margin: 0; }
.p-0 { padding: 0; }
.mt-0 { margin-top: 0; }
.pt-0 { padding-top: 0; }
.mr-0 { margin-right: 0; }
.pr-0 { padding-right: 0; }
.mb-0 { margin-bottom: 0; }
.pb-0 { padding-bottom: 0; }
.ml-0 { margin-left: 0; }
.pl-0 { padding-left: 0; }
.mx-0 { margin-left: 0; margin-right: 0; }
.px-0 { padding-left: 0; padding-right: 0; }
.my-0 { margin-top: 0; margin-bottom: 0; }
.py-0 { padding-top: 0; padding-bottom: 0; }
.m-auto { margin: auto; }
.p-auto { padding: auto; }
.mt-auto { margin-top: auto; }
.pt-auto { padding-top: auto; }
.mr-auto { margin-right: auto; }
.pr-auto { padding-right: auto; }
.mb-auto { margin-bottom: auto; }
.pb-auto { padding-bottom: auto; }
.ml-auto { margin-left: auto; }
.pl-auto { padding-left: auto; }
.mx-auto { margin-left: auto; margin-right: auto; }
.px-auto { padding-left: auto; padding-right: auto; }
.my-auto { margin-top: auto; margin-bottom: auto; }
.py-auto { padding-top: auto; padding-bottom: auto; }
.m-1 { margin: 0.25rem; }
.p-1 { padding: 0.25rem; }
.mt-1 { margin-top: 0.25rem; }
.pt-1 { padding-top: 0.25rem; }
.mr-1 { margin-right: 0.25rem; }
.pr-1 { padding-right: 0.25rem; }
.mb-1 { margin-bottom: 0.25rem; }
.pb-1 { padding-bottom: 0.25rem; }
.ml-1 { margin-left: 0.25rem; }
.pl-1 { padding-left: 0.25rem; }
.mx-1 { margin-left: 0.25rem; margin-right: 0.25rem; }
.px-1 { padding-left: 0.25rem; padding-right: 0.25rem; }
.my-1 { margin-top: 0.25rem; margin-bottom: 0.25rem; }
.py-1 { padding-top: 0.25rem; padding-bottom: 0.25rem; }
.m-2 { margin: 0.5rem; }
.p-2 { padding: 0.5rem; }
.mt-2 { margin-top: 0.5rem; }
.pt-2 { padding-top: 0.5rem; }
.mr-2 { margin-right: 0.5rem; }
.pr-2 { padding-right: 0.5rem; }
.mb-2 { margin-bottom: 0.5rem; }
.pb-2 { padding-bottom: 0.5rem; }
.ml-2 { margin-left: 0.5rem; }
.pl-2 { padding-left: 0.5rem; }
.mx-2 { margin-left: 0.5rem; margin-right: 0.5rem; }
.px-2 { padding-left: 0.5rem; padding-right: 0.5rem; }
.my-2 { margin-top: 0.5rem; margin-bottom: 0.5rem; }
.py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }
.m-3 { margin: 1rem; }
.p-3 { padding: 1rem; }
.mt-3 { margin-top: 1rem; }
.pt-3 { padding-top: 1rem; }
.mr-3 { margin-right: 1rem; }
.pr-3 { padding-right: 1rem; }
.mb-3 { margin-bottom: 1rem; }
.pb-3 { padding-bottom: 1rem; }
.ml-3 { margin-left: 1rem; }
.pl-3 { padding-left: 1rem; }
.mx-3 { margin-left: 1rem; margin-right: 1rem; }
.px-3 { padding-left: 1rem; padding-right: 1rem; }
.my-3 { margin-top: 1rem; margin-bottom: 1rem; }
.py-3 { padding-top: 1rem; padding-bottom: 1rem; }
.m-4 { margin: 1.5rem; }
.p-4 { padding: 1.5rem; }
.mt-4 { margin-top: 1.5rem; }
.pt-4 { padding-top: 1.5rem; }
.mr-4 { margin-right: 1.5rem; }
.pr-4 { padding-right: 1.5rem; }
.mb-4 { margin-bottom: 1.5rem; }
.pb-4 { padding-bottom: 1.5rem; }
.ml-4 { margin-left: 1.5rem; }
.pl-4 { padding-left: 1.5rem; }
.mx-4 { margin-left: 1.5rem; margin-right: 1.5rem; }
.px-4 { padding-left: 1.5rem; padding-right: 1.5rem; }
.my-4 { margin-top: 1.5rem; margin-bottom: 1.5rem; }
.py-4 { padding-top: 1.5rem; padding-bottom: 1.5rem; }
.m-5 { margin: 3rem; }
.p-5 { padding: 3rem; }
.mt-5 { margin-top: 3rem; }
.pt-5 { padding-top: 3rem; }
.mr-5 { margin-right: 3rem; }
.pr-5 { padding-right: 3rem; }
.mb-5 { margin-bottom: 3rem; }
.pb-5 { padding-bottom: 3rem; }
.ml-5 { margin-left: 3rem; }
.pl-5 { padding-left: 3rem; }
.mx-5 { margin-left: 3rem; margin-right: 3rem; }
.px-5 { padding-left: 3rem; padding-right: 3rem; }
.my-5 { margin-top: 3rem; margin-bottom: 3rem; }
.py-5 { padding-top: 3rem; padding-bottom: 3rem; }
Here is the scss
$marginKey: "m";
$paddingKey: "p";
$spacer: 1;
$sizeUnit: rem;
$separator: "-";
$sizes: (
("0", 0),
("auto", auto),
("1", $spacer * 0.25),
("2", $spacer * 0.5),
("3", $spacer),
("4", $spacer * 1.5),
("5", $spacer * 3),
);
$positions: (
("t", "top"),
("r", "right"),
("b", "bottom"),
("l", "left"),
("x", "x"),
("y", "y")
);
@function sizeValue($key, $value) {
@if ($key == "0") {
@return 0;
} @else if ($key == "auto") {
@return auto;
} @else {
@return $value + $sizeUnit;
}
}
@each $size in $sizes {
$sizeKey: nth($size, 1);
$sizeValue: nth($size, 2);
.#{$marginKey}#{$separator}#{$sizeKey} {
margin: sizeValue($sizeKey, $sizeValue);
}
.#{$paddingKey}#{$separator}#{$sizeKey} {
padding: sizeValue($sizeKey, $sizeValue);
}
@each $position in $positions {
$posKey: nth($position, 1);
$posValue: nth($position, 2);
.#{$marginKey}#{$posKey}#{$separator}#{$sizeKey} {
@if $posValue == "x" {
margin-left: sizeValue($sizeKey, $sizeValue);
margin-right: sizeValue($sizeKey, $sizeValue);
} @else if $posValue == "y" {
margin-top: sizeValue($sizeKey, $sizeValue);
margin-bottom: sizeValue($sizeKey, $sizeValue);
} @else {
margin-#{$posValue}: sizeValue($sizeKey, $sizeValue);
}
}
.#{$paddingKey}#{$posKey}#{$separator}#{$sizeKey} {
@if $posValue == "x" {
padding-left: sizeValue($sizeKey, $sizeValue);
padding-right: sizeValue($sizeKey, $sizeValue);
} @else if $posValue == "y" {
padding-top: sizeValue($sizeKey, $sizeValue);
padding-bottom: sizeValue($sizeKey, $sizeValue);
} @else {
padding-#{$posValue}: sizeValue($sizeKey, $sizeValue);
}
}
}
}
The scss file can be modified by adding !important to the sizeValue function
@function sizeValue($key, $value) {
@if ($key == "0") {
@return 0 + " " + !important;
} @else if ($key == "auto") {
@return auto + " " + !important;
} @else {
@return $value + $sizeUnit + " " + !important;
}
}
@jgthms I saw your tweet about spacing helper..!!!! it's great.
when it'll be releasing..????? I need spacing very badly..!!!!!
please add it as soon as possible.
Also, anyone can use: https://github.com/kaangokdemir/bulma-spacing
Great addition!
I'm not sure how to handle responsiveness, in order to have mobile/tablet/desktop/widescreen/fullhd version of each spacing helper. If following the above approach, you would have m-0-mobile and m-2-tablet that could be combined.
Different spacing for each breakpoint is a very common thing in our projects. It would be a very useful feature too.
moving to Tailwind, at last
Now that we have spacing helpers, it is a logic move to make them responsive
:)
responsive scss spacing helpers
@each $property, $shortcut in $spacing-shortcuts {
@each $name, $value in $spacing-values {
// Cardinal directions
@each $direction, $suffix in $spacing-directions {
@include mobile {
.#{$shortcut}#{$suffix}-#{$name}-mobile {
#{$property}-#{$direction}: $value !important;
}
}
@include tablet {
.#{$shortcut}#{$suffix}-#{$name}-tablet {
#{$property}-#{$direction}: $value !important;
}
}
@include touch {
.#{$shortcut}#{$suffix}-#{$name}-touch {
#{$property}-#{$direction}: $value !important;
}
}
@include desktop {
.#{$shortcut}#{$suffix}-#{$name}-desktop {
#{$property}-#{$direction}: $value !important;
}
}
@include widescreen {
.#{$shortcut}#{$suffix}-#{$name}-widescreen {
#{$property}-#{$direction}: $value !important;
}
}
@include fullhd {
.#{$shortcut}#{$suffix}-#{$name}-fullhd {
#{$property}-#{$direction}: $value !important;
}
}
}
// Horizontal axis
@if $spacing-horizontal != null {
@include mobile {
.#{$shortcut}#{$spacing-horizontal}-#{$name}-mobile {
#{$property}-left: $value !important;
#{$property}-right: $value !important;
}
}
@include tablet {
.#{$shortcut}#{$spacing-horizontal}-#{$name}-tablet {
#{$property}-left: $value !important;
#{$property}-right: $value !important;
}
}
@include touch {
.#{$shortcut}#{$spacing-horizontal}-#{$name}-touch {
#{$property}-left: $value !important;
#{$property}-right: $value !important;
}
}
@include desktop {
.#{$shortcut}#{$spacing-horizontal}-#{$name}-desktop {
#{$property}-left: $value !important;
#{$property}-right: $value !important;
}
}
@include widescreen {
.#{$shortcut}#{$spacing-horizontal}-#{$name}-widescreen {
#{$property}-left: $value !important;
#{$property}-right: $value !important;
}
}
@include fullhd {
.#{$shortcut}#{$spacing-horizontal}-#{$name}-fullhd {
#{$property}-left: $value !important;
#{$property}-right: $value !important;
}
}
}
// Vertical axis
@if $spacing-vertical != null {
@include mobile {
.#{$shortcut}#{$spacing-vertical}-#{$name}-mobile {
#{$property}-top: $value !important;
#{$property}-bottom: $value !important;
}
}
@include tablet {
.#{$shortcut}#{$spacing-vertical}-#{$name}-tablet {
#{$property}-top: $value !important;
#{$property}-bottom: $value !important;
}
}
@include touch {
.#{$shortcut}#{$spacing-vertical}-#{$name}-touch {
#{$property}-top: $value !important;
#{$property}-bottom: $value !important;
}
}
@include desktop {
.#{$shortcut}#{$spacing-vertical}-#{$name}-desktop {
#{$property}-top: $value !important;
#{$property}-bottom: $value !important;
}
}
@include widescreen {
.#{$shortcut}#{$spacing-vertical}-#{$name}-widescreen {
#{$property}-top: $value !important;
#{$property}-bottom: $value !important;
}
}
@include fullhd {
.#{$shortcut}#{$spacing-vertical}-#{$name}-fullhd {
#{$property}-top: $value !important;
#{$property}-bottom: $value !important;
}
}
}
}
}
Most helpful comment
Following @ilicmarko's comment, here's my
spacing.scssfile……which generates the following classes…
…and is configurable by changing the values of
$sizeUnit(rem, em, px),$marginKey('m', 'marg', 'margin', etc),$paddingKey('p', 'pad', 'padding', etc),$separator('-', '_', '' for none, etc) and$sizes(whatever keys/values you need).👍