I Want to convert below mentioned CSS format to SCSS using variables or methods. Please suggest how to achieve.
CSS Format is:
.section-1-1{
margin-left:0;
}
.section-1-1 + .section-1-2 {
margin-left: 15px;
}
.section-1-1 + .section-1-3 {
margin-left: 15px;
}
.section-2-1{
margin-left:0;
}
.section-2-1 + .section-2-2 {
margin-left: 15px;
}
.section-2-1 + .section-2-3 {
margin-left: 15px;
}
Note: I may have to write more like .section-3-1, .section-4-1.... vice versa.
With sass you can clean up your code like this, no need to create variables.
.section-1-1 {
margin-left: 0;
+ {
.section-1-2 {
margin-left: 15px;
}
.section-1-3 {
margin-left: 15px;
}
.section-x { } ...
}
}
.section-2-1 { .... }
If you have a lot of classes, you can create classes in a loop.
#for $i from 1 through 3 {
.section-#{$i}-1 {
margin-left: 0px;
}
#for $j from 1 through 3 {
.section-#{$i}-1 + .section-#{$i}-#{$j} {
margin-left: 15px;
}
}
}
This will generate the following CSS.
.section-1-1 {
margin-left: 0px;
}
.section-1-1 + .section-1-1 {
margin-left: 15px;
}
.section-1-1 + .section-1-2 {
margin-left: 15px;
}
.section-1-1 + .section-1-3 {
margin-left: 15px;
}
.section-2-1 {
margin-left: 0px;
}
.section-2-1 + .section-2-1 {
margin-left: 15px;
}
.section-2-1 + .section-2-2 {
margin-left: 15px;
}
.section-2-1 + .section-2-3 {
margin-left: 15px;
}
.section-3-1 {
margin-left: 0px;
}
.section-3-1 + .section-3-1 {
margin-left: 15px;
}
.section-3-1 + .section-3-2 {
margin-left: 15px;
}
.section-3-1 + .section-3-3 {
margin-left: 15px;
}
Use CSS to SCSS converter: https://beautifytools.com/css-to-scss-converter.php
Here's the converter's output for your CSS:
.section-1-1 {
margin-left: 0;
+ {
.section-1-2 {
margin-left: 15px;
}
.section-1-3 {
margin-left: 15px;
}
}
}
.section-2-1 {
margin-left: 0;
+ {
.section-2-2 {
margin-left: 15px;
}
.section-2-3 {
margin-left: 15px;
}
}
}
Is there a way to use {$} to get the most direct parent?
In the example below '&#{&}' is not working as I expected, I managed to work around it using mixin.
#mixin modifier($modifier, $block: &) {
&#{"."+$block}--#{$modifier} {
#content;
}
}
.namespace{
$button : 'btn';
.#{$button} {
line-height: 1;
#include modifier('big', $button){ // working but not clean
padding-top: 8px;
}
&#{&}--big{ // not working as {&} is interpolated to namespace .btn
padding-top: 12px;
}
}
}
Compiled to:
.namespace .btn {
line-height: 1;
}
.namespace .btn.btn--big {
padding-top: 8px;
}
.namespace .btn.namespace .btn--big {
padding-top: 12px;
}
The construct looks a bit odd to me – but you could do it like:
.namespace {
$class: ".btn";
#{$class} { line-height: 1; }
#{$class}#{$class}--big { padding-top: 8px; }
& #{$class}#{&} #{$class}--big { padding-top: 12px; }
}
...or using selector append
.namespace .btn {
line-height: 1;
#at-root {
#{selector-append(&,".btn")}--big{ padding-top: 8px; }
#{selector-append(&,&)}--big{ padding-top: 12px; }
}
}
both compiling to:
.namespace .btn { line-height: 1; }
.namespace .btn.btn--big { padding-top: 8px; }
.namespace .btn.namespace .btn--big { padding-top: 12px; }
I've searched extensively, and can't seem to find a consistent way that people handle the top/bottom margins between modules in a... modular way. I like the idea of just using a generic wrapper div with the css as .page-area { margin-bottom: 1em }, but in the real world, designers aren't that consistent, and you end up with multiple variations on that container. I've used this sass code on a few projects, and it worked alright, but I didn't necessarily love it (credit to Nicole Sullivan):
*p,m = padding,margin
*a,t,r,b,l,h,v = all,top,right,bottom,left,horizontal,vertical
*s,m,l,n = small($space-half),medium($space),large($space-double),none(0)
*/
$space : 1em;
$space-half : $space/2;
$space-double : $space*2;
.ptn, .pvn, .pan { padding-top: 0; }
.pts, .pvs, .pas { padding-top: $space-half; }
.ptm, .pvm, .pam { padding-top: $space; }
.ptl, .pvl, .pal { padding-top: $space-double; }
.prn, .phn, .pan { padding-right: 0; }
.prs, .phs, .pas { padding-right: $space-half; }
.prm, .phm, .pam { padding-right: $space; }
.prl, .phl, .pal { padding-right: $space-double; }
.pbn, .pvn, .pan { padding-bottom: 0; }
.pbs, .pvs, .pas { padding-bottom: $space-half; }
.pbm, .pvm, .pam { padding-bottom: $space; }
.pbl, .pvl, .pal { padding-bottom: $space-double; }
.pln, .phn, .pan { padding-left: 0; }
.pls, .phs, .pas { padding-left: $space-half; }
.plm, .phm, .pam { padding-left: $space; }
.pll, .phl, .pal { padding-left: $space-double; }
.mtn, .mvn, .man { margin-top: 0; }
.mts, .mvs, .mas { margin-top: $space-half; }
.mtm, .mvm, .mam { margin-top: $space; }
.mtl, .mvl, .mal { margin-top: $space-double; }
.mrn, .mhn, .man { margin-right: 0; }
.mrs, .mhs, .mas { margin-right: $space-half; }
.mrm, .mhm, .mam { margin-right: $space; }
.mrl, .mhl, .mal { margin-right: $space-double; }
.mbn, .mvn, .man { margin-bottom: 0; }
.mbs, .mvs, .mas { margin-bottom: $space-half; }
.mbm, .mvm, .mam { margin-bottom: $space; }
.mbl, .mvl, .mal { margin-bottom: $space-double; }
.mln, .mhn, .man { margin-left: 0; }
.mls, .mhs, .mas { margin-left: $space-half; }
.mlm, .mhm, .mam { margin-left: $space; }
.mll, .mhl, .mal { margin-left: $space-double; }
I realize that questions like this can potentially start discussions, but that's not my intent - I'm just wondering if there is a single common best practice for consistent vertical margin/padding of modules and page sections? SMACSS doesn't seem to touch on it.
I don't know if this will be helpful for you, but this is usually what I do.
I set a vertical rhythm variable based on my defaults, and then make a placeholder class for vertical rhythm, which I extend on elements that need it.
$base-font-size: 20px !default
$base-line-height: 1.3
$base-vertical-rhythm: ceil($base-font-size * $base-line-height)
%base-vertical-rhythm
margin-bottom: em($base-vertical-rhythm)
blockquote,
dl,
ol,
p,
ul
#extend %base-vertical-rhythm
Compass also has some presets for vertical rhythm.
I'm trying to create standard classes that can be used to add different amounts of padding. This would be added to the individual elements within the DOM to control padding/margins. I'd like to eventually leverage it for different sizes and for margins as well. This is how I've begun to write it in LESS, but is there a shorter way to write this?
#padding-sm: 5px;
#padding-md: 10px;
#padding-lg: 20px;
.padding-sm {
padding: #padding-sm;
}
.padding-sm-h {
padding-right: #padding-sm;
padding-left: #padding-sm;
}
.padding-sm-v {
padding-top: #padding-sm;
padding-bottom: #padding-sm;
}
.padding-sm-top {
padding-top: #padding-sm;
}
.padding-sm-right {
padding-right: #padding-sm;
}
.padding-sm-bottom {
padding-bototm: #padding-sm;
}
.padding-none {
padding: 0;
}
For LESS 1.7+
This uses the .for looping code that can be found here, which is normally recommended to be saved in a separate less file and imported, like so:
#import "for";
Assuming that code is in place, whether by import or hard copied in, then you can build the following mixin:
.setPadding(#size) {
#s: ~"-#{size}";
#getSize: ~"padding#{s}";
#getValue: ##getSize;
#directions: top right bottom left;
#pairs: h right left, v top bottom;
.appendPadding() {.padding& { #props();}}
#{s} {
//set all directions
& {
#props: {padding: #getValue;};
.appendPadding();
}
//set paired directions
& {
.for(#pairs); .-each(#pair) {
#name: extract(#pair, 1);
#one: extract(#pair, 2);
#two: extract(#pair, 3);
&-#{name} {
#props: {
padding-#{one}: #getValue;
padding-#{two}: #getValue;
};
.appendPadding();
}
}
}
//set four base directions
& {
.for(#directions); .-each(#dir) {
&-#{dir} {
#props: {padding-#{dir}: #getValue;};
.appendPadding();
}
}
}
}
}
Now the above looks vastly more complicated than your original code, but it gets its power by its ability to easily reproduce for all your sizing levels. So with the above code, then the following minimal amount of code defines your three groups into CSS as you are desiring:
#padding-sm: 5px;
#padding-md: 10px;
#padding-lg: 20px;
.setPadding(sm);
.setPadding(md);
.setPadding(lg);
.padding-none {
padding: 0;
}
CSS Output
.padding-sm {
padding: 5px;
}
.padding-sm-h {
padding-right: 5px;
padding-left: 5px;
}
.padding-sm-v {
padding-top: 5px;
padding-bottom: 5px;
}
.padding-sm-top {
padding-top: 5px;
}
.padding-sm-right {
padding-right: 5px;
}
.padding-sm-bottom {
padding-bottom: 5px;
}
.padding-sm-left {
padding-left: 5px;
}
.padding-md {
padding: 10px;
}
.padding-md-h {
padding-right: 10px;
padding-left: 10px;
}
.padding-md-v {
padding-top: 10px;
padding-bottom: 10px;
}
.padding-md-top {
padding-top: 10px;
}
.padding-md-right {
padding-right: 10px;
}
.padding-md-bottom {
padding-bottom: 10px;
}
.padding-md-left {
padding-left: 10px;
}
.padding-lg {
padding: 20px;
}
.padding-lg-h {
padding-right: 20px;
padding-left: 20px;
}
.padding-lg-v {
padding-top: 20px;
padding-bottom: 20px;
}
.padding-lg-top {
padding-top: 20px;
}
.padding-lg-right {
padding-right: 20px;
}
.padding-lg-bottom {
padding-bottom: 20px;
}
.padding-lg-left {
padding-left: 20px;
}
.padding-none {
padding: 0;
}
I use LESS CSS. My code looks like this.
Repeatable pattern
Do you see the pattern in my code? The only thing that differs the two is the padding value and the class name.
Question
Is it possible in LESS CSS to make a function / mixin of a block like this with many different elements?
LESS CSS
&.pad-10 > [class*='cols-'] {
background: #ccc;
padding: 10px;
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
}
}
&.pad-20 > [class*='cols-'] {
background: #ccc;
padding: 20px;
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
}
}
Mixin suggestion
do_padding( $value ) {
&.pad-#value > [class*='cols-'] {
background: #ccc;
padding: #valuepx;
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
}
}
do_padding( 10 );
do_padding( 20 );
I know that my exact problem can be solved in other ways without LESS CSS, but I have this problem from time to time.
Yes, you just need to set up a proper counting and looping structure in LESS. Here's how:
LESS
.do_padding(#startValue, #increment) {
.loop(#value) when (#value > 0) {
//set top amount
&.pad-#{value} > [class*='cols-'] {
background: #ccc;
padding: #value * 1px;
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
}
}
// next iteration
.loop(#value - #increment);
}
// end the loop when index is 0 or less
.loop(#value) when not (#value > 0) {}
//start the loop
.loop(#startValue);
}
Use it
.myClass {
.do_padding(30, 10);
}
CSS Output
.myClass.pad-30 > [class*='cols-'] {
background: #ccc;
padding: 30px;
}
.myClass.pad-30 > [class*='cols-']:first-child {
padding-left: 0;
}
.myClass.pad-30 > [class*='cols-']:last-child {
padding-right: 0;
}
.myClass.pad-20 > [class*='cols-'] {
background: #ccc;
padding: 20px;
}
.myClass.pad-20 > [class*='cols-']:first-child {
padding-left: 0;
}
.myClass.pad-20 > [class*='cols-']:last-child {
padding-right: 0;
}
.myClass.pad-10 > [class*='cols-'] {
background: #ccc;
padding: 10px;
}
.myClass.pad-10 > [class*='cols-']:first-child {
padding-left: 0;
}
.myClass.pad-10 > [class*='cols-']:last-child {
padding-right: 0;
}