How to #extend without class name in sass? - css

Is there any way to extend class if parent has no class name in sass?
scss
div {
&:last-child {
margin: 1rem;
div {
#extend from parent here i.e. &:last-child
}
}
}
#extend &:last-child does not seem to work.

(To answer my own question), You can use the #at-root directive to move child selector to the root level so that it can extend the parent selector.
scss
div {
&:last-child {
margin: 1rem;
div {
#at-root div:last-child {
#extend div:last-child;
margin: 0;
}
}
}
}
css output
div:last-child {
margin: 1rem;
}
div:last-child {
margin: 0;
}

Related

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

how to extends only specific rules in parent class to child class, rather than all of them in sass?

I have a parent class called .parent-form and I want to extend some of its rules in the child class, not all of them. Is that possible in SASS?
.parent-form {
padding: 20px 10px;
.form-control:focus {
border-color: #2BBBAD;
}
.row {
/*some css rules goes here*/
}
}
.child-form {
#extend .parent-form;
/* I only need padding and .form-control, but not .row */
}
Is there any way to do that kind of thing in sass?
You cannot selectively extend rules in a class while not taking the others. However you could do something like this:
.parent-form {
padding: 20px 10px;
.form-control:focus {
border-color: #2BBBAD;
}
}
.child-form {
#extend .parent-form;
}
.needs-row {
#extend .parent-form;
.row {
}
}
.child-form-with-row {
#extend .needs-row;
}
Alternatively, you could do this with a mixin:
#mixin need-row($needRow) {
#extend .parent-form;
#if $needRow == true {
.row {
}
}
}
.child-form-with-row {
#include need-row(true);
}

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.

Sass to css output

I think this is the way to do it but my css output is not what I was expecting:
SOURCE CODE
This is my scss file:
footer.page-footer
{
margin-top: 0;
&,
nav
{
background-color: $blue;
}
}
This is the css output:
footer.page-footer
{
margin-top: 0;
}
footer.page-footer,
footer.page-footer nav
{
background-color: #50a4b1;
}
How can I make the second outputted css's selector be simply footer.page-footer, nav instead of footer.page-footer, footer.page-footer nav?
You can use the #at-root directive to produce a rule that is generated outside its definition scope but that retains the value of its parent (&)
footer.page-footer {
margin-top: 0;
#at-root {
#{&},
nav {
background-color: blue;
}
}
}
Output:
footer.page-footer {
margin-top: 0;
}
footer.page-footer,
nav {
background-color: blue;
}
<p class="sassmeister" data-gist-id="93b3b22a2888f2f5f86b" data-height="480" data-theme="tomorrow">Play with this gist on SassMeister.</p><script src="http://cdn.sassmeister.com/js/embed.js" async></script>
Sassmeister

SASS: content block mixin (or placeholder) that takes contextual selectors and appends them to selector in mixin

I want to do something like this:
#mixin context($size) {
body.#{$size} {
#content
}
}
div {
span {
font-size: 2em;
#include context('large') {
& {
font-size: 5em;
}
}
}
}
To produce:
div span {
font-size: 2em;
}
body.large div span {
font-size: 5em;
}
What it ACTUALLY (predictably) produces:
div span {
font-size: 2em;
}
div span body.large {
font-size: 5em;
}
I could just replicate the selectors inside different mixins, but given that selectors could be complex that's a lot of extra junk:
#include context('large') {
div {
span {
font-size: 5em;
}
}
}
I could make the selectors into mixins so I don't have to repeat them each time, but...
Isn't there a way to use placeholders, maybe in combination with mixins, to get what I want in the first two code blocks above?
You just need to move the & to be part of the mixin:
#mixin context($size) {
body.#{$size} & {
#content
}
}
div {
span {
font-size: 2em;
#include context('large') {
font-size: 5em;
}
}
}
Output:
div span {
font-size: 2em;
}
body.large div span {
font-size: 5em;
}
As of Sass 3.4, you can write this to work both inside a selector and at the root of the document:
#mixin optional-at-root-nest($sel) {
#at-root #{if(not &, $sel, selector-nest($sel, &))} {
#content;
}
}
#mixin context($size) {
#include optional-at-root-nest('body.#{$size}') {
#content
}
}
div {
span {
font-size: 2em;
#include context('large') {
font-size: 5em;
}
}
}
#include context('large') {
font-size: 2em;
}

Resources