How to overwrite Referencing Parent Selector using Mixin in SCSS - css

I had a common used component and its scss is like this:
.component {
margin-right: 12px;
&.specified-use-case {
margin-right: 30px;
&:nth-child(odd) {
margin-right: 70px
}
}
}
Now I want everything has same style in mobile view
.component {
margin-right: 12px;
// some predefined mixin
#include viewport(mobile) {
margin-right: 0px;
margin-bottom: 14px;
}
&.specified-use-case {
margin-right: 30px;
&:nth-child(odd) {
margin-right: 70px
}
}
}
But this can't change style for "specified-use-case" in mobile view. In order to do it I have to
.component {
margin-right: 12px;
// some predefined mixin
#include viewport(mobile) {
margin-right: 0px;
margin-bottom: 14px;
}
&.specified-use-case {
margin-right: 30px;
#include viewport(mobile) {
margin-right: 0px;
margin-bottom: 14px;
}
&:nth-child(odd) {
margin-right: 70px
#include viewport(mobile) {
margin-right: 0px;
margin-bottom: 14px;
}
}
}
}
Which just doesn't seem right to me. Is there a better way to define mobile view css just for once?

According to CSS' specificity rules (try this calculator) you unfortunately need to repeat yourself. What your SCSS interpreter does is just compiling what you've written to standard CSS, which will look something akin to:
.component {
margin-right:12px
}
#media (max-width:768px) {
.component {
margin-right:0px;
margin-bottom:14px
}
}
.component.specified-use-case {
margin-right:30px
}
#media (max-width:768px) {
.component.specified-use-case {
margin-right:0px;
margin-bottom:14px
}
}
.component.specified-use-case:nth-child(odd) {
margin-right:70px
}
#media (max-width:768px) {
.component.specified-use-case:nth-child(odd) {
margin-right:0px;
margin-bottom:14px
}
}
As you can see, you're overriding each class with a #media ruleset just after it has been declared. And since I'm a big proponent to never use !important (because you'll open a pandoras box), the only way you can shorten your SCSS is doing:
.component {
margin-right: 12px;
// some predefined mixin
#include viewport(mobile) {
margin-right: 0px;
margin-bottom: 14px; // only need to define margin-bottom once, here.
}
&.specified-use-case {
margin-right: 30px;
#include viewport(mobile) {
margin-right: 0px;
//margin-bottom: 14px;, remove this
}
&:nth-child(odd) {
margin-right: 70px
#include viewport(mobile) {
margin-right: 0px;
//margin-bottom: 14px;, remove this
}
}
}
}
Hope this helps!

You can put the rules inside of the media query:
#include viewport(mobile) {
margin-right: 0px;
margin-bottom: 14px;
&.specified-use-case {
margin-right: 0px;
margin-bottom: 14px;
}
}

seems like sass is wrong because you specify margins above a breakpoint, try this:
.component {
margin-right: 12px;
&.specified-use-case {
margin-right: 30px;
&:nth-child(odd) {
margin-right: 70px
}
}
// some predefined mixin
#include viewport(mobile) {
margin-right: 0px;
margin-bottom: 14px;
}
}

Related

How to inject literal string into scss #mixin

Considering this following scss code:
#mixin homeSlider(
$dim: 150px,
$h1: "h1 { font-size: 4em; margin-top: 0; }"
){
section {
margin-top: -$dim;
}
$h1;
}
#include homeSlider( $dim: 50px, $h1: "h1 { font-size: 3em; margin-top: 0; }" )
I need to know how is it possible to achieve my goal
Try this
#mixin homeSlider($dim, $h1-font-size){
section {
margin-top: -$dim;
h1 {
font-size: $h1-font-size;
margin-top: 0;
}
}
}
#include homeSlider(50px, 3em;) /* $dim = 50px - $h1-font-size = 3em; */

how to get the direct parent in sass interpolation of &

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; }

Mobile First Breakpoints for nth child

I have this code that works, it is a group of client icons that starts off with a 2 column list on mobile, then gradually moves to a 3 column list and then onto a 4 column list and so on.
I am using the nth child pseudo element to remove the margin on certain numbers depending on the breakpoint i.e :nth-child(2n) on the column breakpoint.
But check my code out I feel it is messy, Does anyone know of a better way to write this?
.list-horiz-images li {
float: left;
margin-right: 7px;
margin-bottom: 7px;
width: 49%;
&:nth-child(2n) {
margin-right: 0px;
}
#include mobilefirst(em(670)) {
width: 32.57%;
&:nth-child(2n) {
margin-right: 7px;
}
&:nth-child(3n) {
margin-right: 0px;
}
}
#include mobilefirst(em(1024)) {
width: 24.44%;
&:nth-child(2n) {
margin-right: 7px;
}
&:nth-child(3n) {
margin-right: 7px;
}
&:nth-child(4n) {
margin-right: 0px;
}
}
#include mobilefirst(em($bp-large)) {
width: 13.666666666%;
&:nth-child(2n) {
margin-right: 7px;
}
&:nth-child(3n) {
margin-right: 7px;
}
&:nth-child(4n) {
margin-right: 7px;
}
}
}

Scalable/Modular CSS: how to handle vertical margins between modules?

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.

Making use of CSS vs Sass (SCSS) - base class issues and redundency

I'm trying to clean up my CSS to be cleaner by using SCSS.
Standard CSS:
.dark-hr,
.light-hr {
width: 100%;
height: 1px;
margin: 15px 0px;
}
.dark-hr {
background-color: #595959;
}
.light-hr {
background-color: #cccccc;
}
vs SCSS:
.generic-hr {
width: 100%;
height: 1px;
margin: 15px 0px;
}
.dark-hr {
#extend .generic-hr;
background-color: #595959;
}
.light-hr {
#extend .generic-hr;
background-color: #cccccc;
}
Is there any way to avoid creating the 'generic-hr' class that won't be used? I was hoping that some kind of nest would work well.
In this scenario the CSS is definitely way cleaner and more readable than SCSS.
Ideally I would need this to work in SCSS:
.## {
// base class that is not outputted
.dark-hr {
//attributes the extend the base class '.##'
}
.light-hr {
//attributes the extend the base class '.##'
}
}
OUTPUT:
.dark-hr, .light-hr {
//shared attributes defined by '.##'
}
.dark-hr {
// overrides
}
.light-hr {
// overrides
}
What you're wanting to use is an extend class (I call them "silent classes"), which is signified by using a % instead of a ..
hr%base {
width: 100%;
height: 1px;
margin: 15px 0px;
}
.dark-hr {
#extend hr%base;
background-color: #595959;
}
.light-hr {
#extend hr%base;
background-color: #cccccc;
}
Wouldn't you normally do something like this:
.generic-hr {
width: 100%;
height: 1px;
margin: 15px 0px;
&.dark {
background-color: #595959;
}
&.light {
background-color: #cccccc;
}
}
My pattern for this kind of thing is a mixin:
#mixin generic-hr {
width: 100%;
height: 1px;
margin: 15px 0px;
}
.dark-hr {
#include generic-hr;
background-color: #595959;
}
.light-hr {
#include generic-hr;
background-color: #cccccc;
}
This has the added advantage of being extensible, so if you find yourself needing several selectors with really similar properties you can add in variables:
#mixin generic-hr($background-color: transparent) {
width: 100%;
height: 1px;
margin: 15px 0px;
background-color: $background-color;
}
.dark-hr {
#include generic-hr(#595959);
}
.light-hr {
#include generic-hr(#cccccc);
}
.medium-hr {
#include generic-hr(#818181);
}

Resources