Sass ampersand and parent styles - css

My HTML:
<div id="form" class="special">
<div class="header">My special form</div>
<div>
And the following sass code:
#form {
.header {
padding: 20px 10px;
.special & {
background: $special-color;
}
}
}
Which produces:
#form .header {
padding: 20px 10px;
}
.special #form .header {
background: #7cc52c;
}
However this doesn't give me the result I want. Instead of the CSS above I want to have: .special#form .header (the element form with class special, not the element .special which has form)

You can achieve your desired css this way.
#form {
.header {
padding: 20px 10px;
#at-root #{selector-replace(&, '#form', '.special#form')} {
background: blue;
}
}
}
This scss compiles to the following css
#form .header {
padding: 20px 10px;
}
.special#form .header {
background: blue;
}
Using the selector-replace function, you can easily change the part of the compound selector that needs changing. In this example, that would be replacing #form with .special#form. The #at-root directive ensures that the selector is placed at the top level and not nested within any selector.
When the parent selector is appended and nested as you did in your question, it reverses the selector. There are situations where this might be useful, one such situation is when working with Modernizr as illustrated in one of the slides on here
Hope this helps.

The simplest way to do this is by using #at-root and interpolation
$special-color:#7cc52c;
#form {
.header {
padding: 20px 10px;
// use #at-root to move .special out of #form .header
#at-root {
// append #form .header using the & selector
// note! you need to use interpolation #{} to
// remove the white space between .special and #form
.special#{&} {
background: $special-color;
}
}
}
}

Related

style priority not working as expected in SASS

I have the following scss styles defined in a separate file
.radio-button-focused {
background-color: $PURPLE;
text-align: left;
opacity: 1;
width: px-to-rem(1248px);
margin-bottom: px-to-rem(15px);
#include truncate;
}
.radio-button {
background-color: $BLACK;
text-align: left;
opacity: 1;
width: px-to-rem(1248px);
margin-bottom: px-to-rem(15px);
#include truncate;
}
Both of them are being applied to a button
But the problem is that radio button is overwritting the color of radio-button-focused
I understand that I could use !important , or just use one of them instead of using them both at the same time. But if I was forced to use both, can something else be done to fix this?
The literal order in the CSS file matters. If two rules have the same specificity, the last one is applied. Move .radio-button before .radio-button-focused. You could also make your focused selector more specific. .radio-button.radio-button-focused for example.
Here's class B before A as an example.
.b
{
color: red;
}
.a
{
color: blue;
}
<div class="a b">Hi</div>
And here's A before B.
.a
{
color: blue;
}
.b
{
color: red;
}
<div class="a b">Hi</div>

How to optimize two css classes into one

I have a project made with react and I want to optimize the css.
I have this code:
.class-1 {
margin-top: 15px;
}
.class-2 {
margin-bottom: 15px;
}
Is there a possible way to optimize like this during the build?
.class-3 {
margin: 15px 0 15px 0;
}
You can add both classes to your HTML element or combine the margins into one class like this:
.class1 {
margin-top: 15px;
background-color: skyblue;
}
.class2 {
margin-bottom: 15px;
}
.class3 {
margin: 15px 0;
background-color: red;
}
<div class='class1 class2'>My element with 2 classes</div>
<div class='class3'>My element with 1 class</div>
It all depends if you want to keep the classes separate for other areas of your code, or if you will never need those margins in separate classes.

Merging selector #extend issue

I have a problem about "#extend" directive in SCSS.
.header {
.introduction-group {
text-align: center;
color: $white;
width: 70%;
}
.about {
&__description-group {
#extend .introduction-group;
This code block does not work. However,
.header {
&__introduction-group {
text-align: center;
color: $white;
width: 70%;
}
.about {
&__description-group {
#extend .header__introduction-group;
Second one works. Why?
Thank you.
As mentioned here nested classes won't be applied with #extend. Your second code block targets the specified class including the parent prefix. The first code block doesn't, it only targets the nested class.
I made a small codepen demo to illustrate the problem in a simple way. Make sure you checkout the Sass docs for a more comprehensive explanation!
<h1 class="wrong">Test style gone wrong</h1>
<h1 class="right">Test style gone right</h1>
.test {
.nested {
color: red;
}
&-nested {
color: red;
}
}
.wrong {
#extend .test;
#extend .nested;
}
.right {
#extend .test-nested;
}

SCSS/SASS - How to Specify Two Valid Parents for Nested CSS

Question: With SCSS, can we specify two different .main selectors? Say I want another one with margin-top: 50px while also inheriting all other conditions
I have inherited some SCSS from someone else. I have the following SCSS structure:
.main {
margin-top: 74px;
ul.tabs {
position: relative;
li.tab {
/*The rest of nested structure*/
}
}
}
It continues to nest (unfortunately) for many layers.
I have some other options (splitting the structure in two) which is a simple fix. Just curious if there's something better.
Thanks!
You should use a mixin:
#mixin sharedStyles{
//shared nested styles go here
}
.parentA{
margin-top:74px;
#include sharedStyles;
}
.parentB{
margin-top: 50px;
#include sharedStyles;
}
Here is a gist that illustrates the concept:
https://gist.github.com/Ryan-Haines/ba10888d0828d394851d3da6063f70bb
I recommend using sassmeister for rapid prototyping:
https://www.sassmeister.com
If you use a placeholder, as long as one selector is not inside a media query, it should group them together in the CSS. Ie
%mainStyles {
border: 1px solid black;
}
.main1 {
margin-top: 75px;
#extend %mainStyles;
}
.main2 {
margin-top: 50px;
#extend %mainStyles;
}
Should generate
.main1, .main2 {
border: 1px solid black;
}
.main1 {
margin-top: 75px;
}
.main2 {
margin-top: 50px;
}

SASS Ampersand – Chaining CSS class with the parent selector '&' like in LESS

LESS (CSS)
see in action
.app {
#page {
.inner {
.left {
&.padding-left-10px {
padding-left: 10px;
// rtl direction
.rtl& { //////////////////////////////////
padding-left: 0;
padding-right: 10px;
}
}
}
}
}
}
Consider the line I have highlighted with ///.....
I want the same result in SASS (.scss). Is it possible?
Expected result should be:
.rtl.app #page .inner .left.padding-left-10px {}
and not
.rtl .app #page .inner .left.padding-left-10px {}
Thanks.
It looks like you are attempting to use the LESS feature where you can change the order of the selectors by using the parent selector. It isn't working as expected because that specific LESS feature isn't implemented the same way in SASS.
If you want the equivalent output code in SASS, then you can use the #at-root directive in order to scope the selector to the root. Then you would also need to use variable interpolation (i.e., .rtl#{&}) for the parent selector:
.app {
#page {
.inner {
.left {
&.padding-left-10px {
padding-left: 10px;
#at-root {
.rtl#{&} {
padding-left: 0;
padding-right: 10px;
}
}
}
}
}
}
}
Which would compile to:
.app #page .inner .left.padding-left-10px {
padding-left: 10px;
}
.rtl.app #page .inner .left.padding-left-10px {
padding-left: 0;
padding-right: 10px;
}
Josh gave you an answer which will work, i guess. But I still wanna give you some advice and that is look into BEM, or someway. Nesting like this is really unnecessary.
Your code could be better for readability.
For example:
.padding {
padding: 10px;
}
.padding--left { // This is a modifier for padding
padding: 0 0 0 10px;
}
.padding--right { // This is a modifier for padding
padding: 0 10px 0 0;
}
<div class="padding padding--left">Using it in a div</div>
You don't have to follow all the rules which are defined in BEM, but some are really nice to use.

Resources