This question already has an answer here:
-
Ampersand (&) at the end, and part of, a selector in SASS
1 answer
I have a class semantic
which I apply to many different elements. Depending on which html tag the class is applied to, I would like it to apply a different style. This is how I tried to do it:
.semantic {
&ul {
padding: 0;
margin: 0;
}
&p {
margin: 0;
}
}
This doesn't work. Of course I could write it like this, but it wouldn't be very "DRY":
.semantic ul {
padding: 0;
margin: 0;
}
.semantic p {
margin: 0;
}
Is this possible?
Edit: For clarification, here is an example of what my HTML looks like:
<ul class='semantic'>
<li>An Item</li>
</ul>
<p class='semantic'>This text is semantically a paragraph, but should not be displayed as such</p>
What you're wanting for would in theory look like this:
.semantic {
ul& {
padding: 0;
margin: 0;
}
p& {
margin: 0;
}
}
This is not possible because the &
must be first. You're just going to have to deal with the fact that it isn't DRY and write it out by hand:
ul.semantic {
padding: 0;
margin: 0;
}
p.semantic {
margin: 0;
}
As of Sass 3.3 or 3.4, it is possible using this syntax:
.semantic {
ul#{&} {
padding: 0;
margin: 0;
}
p#{&} {
margin: 0;
}
}
On Sass 3.4:
.semantic {
@at-root {
ul#{&} {
padding: 0;
margin: 0;
}
p#{&} {
margin: 0;
}
}
}
Generates:
ul.semantic {
padding: 0;
margin: 0;
}
p.semantic {
margin: 0;
}
@at-root moves the block to the top-level. This has several uses (see link) but here it's being used to keep take advantage of the &
syntax without implying that the rules are child selectors of .semantic
.
Because of how CSS specificity works you could just do this:
.semantic {
margin: 0;
}
ul.semantic {
padding: 0;
}
In your HTML, p.semantic
and ul.semantic
would have margin: 0;
and only ul.semantic
would have padding: 0;
Less Sass, less CSS. DRY.
If, unlike your example, elements on the real site have even less in common, you might want to rethink why they need to have the same class name.
It's not quite clear what HTML structure you have.
If it's like this:
<div class="semantic">
<p>...</p>
<ul>...</ul>
</div>
...then you need classes like .semantic ul
and .semantic p
. Here's an appropriate SCSS:
.semantic {
& ul {
padding: 0;
margin: 0; }
& p {
margin: 0; } }
If HTML structure is like this:
<p class="semantic">...</p>
<ul class="semantic">...</ul>
...then you need classes like .semantic ul
and .semantic p
. You should listen to bookcasey. Here's a sassy version of his DRY suggestion:
.semantic {
padding: 0;
margin: 0; }
p.semantic {
margin: 0; }