When a designer is working on a UI in something like Sketch they will get the spacing to look how they want, normally based on a pre-defined spacing scale.
$space-1: 8px;
$space-2: 16px;
$space-3: 20px;
$space-4: 24px;
$space-5: 32px;
$space-6: 40px;
$space-7: 48px;
$space-8: 56px;
$space-9: 64px;
$space-10: 72px;
These are useful for making sure no magic-numbers are used and also for stepping up or down the scale to give more or less space in an intuitive way.
There are a few problems with doing with variables alone: 1. You will write a specific class for every use, even if al you are doing is adding a little margin. 2. The specific class will need to be set at breakpoints 3. The spacing is the most likely thing to change when a designer is reviewing a UI. Not because its wrong but because of the differences of rendering in design software with sometimes placeholder content and a browser with real content.
You could make a set of responsive utilities, but unfortunately the spacing on mobile can't just be scaled up in a programmatic way to produce a desktop layout. There is as much art as science to the whitespace and you may even use a completely different layout a larger sizes anyway.
$space-5: 32px;
$space-shrink-factor-sm: 0.8;
.margin-b-5 {
margin-bottom: $space-5 * $space-shrink-factor-small;
@media screen and ( min-width: 640px) {
margin-bottom: $space-5;
}
}
After reading the State of CSS 2019 I saw that Tailwindcss had a very high satisfaction rating. There is an ongoing debate on weather CSS utilities are a good thing or not, but my view is that in some cases they are too useful to ignore. I really loved the syntax of the Tailwind so I made a set of utilities that followed the same [breakpoint]:[utility] format in Codepen.
I wanted to make another version with Webpack as a learning exercise.
Here is how it works ...
These could be be hooked into an existing set of breakpoints in your frontend code.
$breakpoints:(
md: 640px,
lg: 1024px,
xl: 1200px,
xxl: 1440px
);
I find these are best to be hard-coded as variables as the almost never change once set by a designer. Also sometimes a designer will throw logic to the wind and break the mathematical pattern at certain points because sometimes logic doesn't look visually pleasing.
/* The variables can be used in component .classes */
$space-1: 8px;
$space-2: 16px;
$space-3: 20px;
...
/* The map is for looping over */
$space: (
1: $space-1,
2: $space-2,
3: $space-3,
...
);
You will need a way to programmatically wrap classes in a breakpoint.
@mixin breakpointWrap($screenSize) {
@media screen and ( min-width: map-get($breakpoints, $screenSize) ) {
@content;
}
};
Then a nested for loop of the breakpoints -> spacing values -> .classes
@each $bpKey, $bgVal in $breakpoints {
@include breakpointWrap($bpKey){
@each $sKey, $sVal in $space {
.#{$bpKey}--m-#{$sKey}{
margin: $sVal;
}
.#{$bpKey}--m-b-#{$sKey}{
margin-bottom: $sVal;
}
...
/* + top, left and right */
.#{$bpKey}--p-#{$sKey} {
padding: $sVal;
}
.#{$bpKey}--p-b-#{$sKey} {
padding-bottom: $sVal;
}
...
/* + top, left and right */
};
};
};
I opted to leave the base 'small' size out of the loops so didn't have to include any conditions.
This can produce a surprizing amount of CSS even when you are sure you only included the useful stuff.
500 css classes and weighted in at about 24kb, which seems like a lot for something so simple.
But you can use purgecss-webpack-plugin to removed unused classes from your source files. I found it takes a few seconds for webpack to do this, so it's probably best left to a production build only. Or this might be better as a NPM script.
Have a look at the working example on GitHub