Sass Ampersand nesting with pseudo selectors - css

Trying to utlize the SASS Ampersand to get the following css output. It is not working when we use Ampersand with inside pesudo selector.
CSS
.test:first-child .test-image { display: block; }
SASS
.test {
&:first-child {
display: inline-block;
&-image {
display: block;
}
}
}
Above code basically cascading the -image with first-child.

This is because the ampersand is just concatenating the parent with the child. If you want the compiled CSS to look like your example you need to do this:
.test {
&:first-child &-image{
display: block;
}
}

If you are trying to achieve
.test:first-child .test-image { display: block; }
With your code it is getting compiled as this
.test:first-child-image {
display: block;
}
Instead ,you can simply write it as this .
.test:first-child {
.test-image {
display: block;
}
}
Hope it helps

It sounds like you have mistaken how the ampersand works in Sass. The ampersand is essentially a shorthand for writing each outer selector and then adding the selector after it onto the end. As .test-image is distinct from .test, you should specify it as follows.
.test {
&:first-child {
.test-image {
display: block;
}
}
}
Compiles to
.test:first-child .test-image {
display: block;
}

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

Referencing parent selectors using the ampersand character, and :not

The article here shows a brilliant example of using an ampersand to reference a parent selector, like so:
h3 {
font-size: 20px;
margin-bottom: 10px;
.some-parent-selector & {
font-size: 24px;
margin-bottom: 20px;
}
}
This works as expected. However, I am following BEM principles and do not wish to have overriding Sass. As you can see in my screenshot below, the styles from .js-tabby overrides the default .tabs code.
I've tried things like:
.tabs {
display: none;
visibility: hidden;
.js-tabby &:not(&) {
display: none;
visibility: hidden;
}
.js-tabby & {
display: block;
visibility: visible;
}
}
But alas, it doesn't work.
As I was writing this question, I had a thought that seemed crazy, but it worked! So, here's my first Q&A ever:
.tabs {
html:not(.js-tabby) & {
display: none;
visibility: hidden;
}
html.js-tabby & {
display: block;
visibility: visible;
}
}
The plugin I'm using attaches the .js-tabby class to the html element, so I targeted that and BOOM! It works.
This has been something that's plagued me for so long, and I hope I can save someone else further frustration.

BEM with SASS and :hover

What's the proper way of declaring active/focus/hover states using BEM with SASS? For example, I have this structure:
<div class="card">
<img class="card__image" src="..." alt="">
<div class="card__overlay">
<div class="card__title"></div>
</div>
</div>
And the SCSS:
.card {
&__image {
}
&__overlay {
}
&__title {
}
}
And I want to modify the elements when hovering on the block.
This doesn't work:
.card {
&__overlay {
display: none;
}
&:hover {
&__overlay {
display: block;
}
}
}
And having to write the whole .project__image just for this one instance seems wrong.
Is there any other way to accomplish this?
You can achieve the desired result using the Sass ampersand selector, without using variables or interpolation.
Referencing parent selectors by using the ampersand (&) can be a
powerful tool, if used right. There are simple uses of this feature as
well as some very complex uses of this feature.
For example:
.card {
&__overlay {
display:none;
}
&:hover & {
&__overlay {
display: block;
}
}
}
Results in:
.card__overlay {
display: none;
}
.card:hover .card__overlay {
display: block;
}
This code uses fewer language constructs (e.g. no use of variables or interpolation) and so is arguably a cleaner implementation.
Read more about interpolation:
http://sass-lang.com/documentation/file.SASS_REFERENCE.html#interpolation_
SCSS:
.card {
$root: &;
&__overlay {
display: none;
#{$root}:hover & {
display: block;
}
}
}
RESULT:
.card__overlay {
display: none;
}
.card:hover .card__overlay {
display: block;
}
PS. It is similar to #alireza safian post, but with this way you don't need to duplicate class name. Variable $root do it for you :)
Alternative way:
Use variable instead of ampersand for third level.
Link
SASS:
$className: card;
.card {
&__overlay {
display: none;
}
&:hover {
.#{$className}__overlay {
display: block;
}
}
}
CSS:
.card__overlay {
display: none;
}
.card:hover .card__overlay {
display: block;
}

Target Parent and Some other selector [duplicate]

This question already has answers here:
Modifying the middle of a selector in Sass (adding/removing classes, etc.)
(2 answers)
Closed 7 years ago.
I'd like to try and target the parent selector, plus also append some other selector to it.
What I want is
.first .second {
display: none;
}
.first.show .second {
display: block;
}
I have tried:
.first {
.second {
display: none;
.show& {
display: block;
}
}
as well as some others. That one seems most logical to me, but apparently you can't have an ampersand directly after a selector.
Any advice?
use
.first {
.second {
display: none;
}
&.show .second {
display: block;
}
}
Reference: http://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector

What does an "&" before a pseudo element in CSS mean?

In the following CSS taken from Twitter Bootstrap what does the ampersand (&) character mean?
.clearfix {
*zoom: 1;
&:before,
&:after {
display: table;
content: "";
}
&:after {
clear: both;
}
}
That's LESS, not CSS.
This syntax allows you to nest selector modifiers.
.clearfix {
&:before {
content: '';
}
}
Will compile to:
.clearfix:before {
content: '';
}
With the &, the nested selectors compile to .clearfix:before.
Without it, they compile to .clearfix :before.
A nested & selects the parent element in both SASS and LESS. It's not just for pseudo elements, it can be used with any kind of selector.
e.g.
h1 {
&.class {
}
}
is equivalent to:
h1.class {
}
Here is an SCSS/LESS example:
a {
text-decoration: underline;
#include padding(15px);
display: inline-block;
& img {
padding-left: 7px;
margin-top: -4px;
}
}
and its equivalent in CSS:
a {
text-decoration: underline;
#include padding(15px);
display: inline-block;
}
a img {
padding-left: 7px;
margin-top: -4px;
}
'&' is useful feature in both Sass and Less preprocessor. For nesting it's used. It is time saver when we compare to CSS.

Resources