Sass: apply a property to a grand-parent with same class - css

I have the markup:
<body class="arabic specific-page">
<div class="child">
<div class="grand-child">
</div>
</div>
</body>
In my sass I am already inside .specific-page and .child. I would like to apply a specific property if body is .arabic:
what I already have:
.specific-page {
.child{
.arabic & {
.grand-child{
gets compilet to:
.arabic .specific-page .child .grand-child
I would like to compile to:
.arabic.specific-page .child .grand-child (body has the same class)
without changing the selector at the top of the tree, only at child level

You can do this using #at-root like so:
.specific-page {
.child{
#at-root .arabic#{&} {
.grand-child{
border: 1px solid red;
}
}
}
}
This compiles to: .arabic.specific-page .child .grand-child, see here.

For this to work you're going to need to alter your SASS a bit. Try
.specific-page {
&.arabic {
.child {
.grand-child {

You could use #at-root and break out of your nesting structure.
.specific-page {
.child{
.arabic {
#at-root .arabic.specific-page .child .grand-child{}
}
}
}

I use an #mixin function like this, when i need change some element in middle
of a sass big tree.
The first parameters is the parent element, the target, and the second the class that should have.
SASS
#mixin parentClass($parentTarget, $aditionalCLass) {
#at-root #{selector-replace(&, $parentTarget, $parentTarget + $aditionalCLass)} {
#content;
}
}
Sample,
like I need to improve font size in a strong tag, when .txt-target had .txt-strong too
HTML
<section class="sample">
<h1 class="txt-target txt-bold">Sample<strong>Bold</strong>Text</h1>
</section>
SASS
section{
.txt-target{
strong{
#include parentClass('.txt-target','.txt-bold'){
font-weight:bold;
font-size:30px;
}
}
}
}

2 options:
.arabic.specific-page {
.child{
.grand-child{
Or (you can switch the order of arabic and specific-page):
.arabic{
&.specific-page {
.child{
.grand-child{

Related

Overwrite css variables

I have a component that declares and use a css variable "--test: red"
But I want to re-declare this variable with a new color outside this component.
https://stackblitz.com/edit/js-va9k9q?file=style.css
Is this rule right?
:root *{
--test: green;
}
Why * is required? If I remove this, it doesn't work
:root *{
--test: green;
}
#app {
--test: red;
}
#app h1{
background-color: var(--test);
}
Html
<html>
<body>
<div id="app"><h1>Example</h1></div>
</body>
</html>
The final result must have a green background-color
Use a second variable in case you want to only consider :root
:root {
--new: green;
}
#app {
--test: red;
}
#app h1 {
background-color: var(--new, var(--test)); /* will fallback to "test" if "new" is not defined */
}
<div id="app">
<h1>Example</h1>
</div>
Or you keep using the code you show which is correct since you will target all the elements (with *) to set the variable --test that will get used instead of the one inherited from #app
This is about ordering and priority of css selectors
if you do like this:
:root {
--test: red;
}
.
.
.
:root {
--test: green;
}
the second selector have more priority
but if you do:
:root #app{
--test: green;
}
.
.
.
:root {
--test: red;
}
the first selector will apply for #app.
if another block is defined outside of #app, it would get red color.
:root * {} works because it have more priority.
read more about priority in this link

CSS - When input:checked, change another class?

This is my class -
.swatch input:checked + label {
background-color: #fff;
}
.swatch {
Change something here when above class is active.
}
Is there any way to do this? I am using liquid templating if that could be of assistance.
No.
It is possible for one ruleset to affect another using CSS variables…
body {
--example: yellow;
}
input:checked+.swatch {
--example: brown;
}
.swatch {
background: var(--example);
}
<input type="checkbox">
<div class="swatch">
Hello, world
</div>
… but that would only allow the variable to be set on the input, it's descendant (if inputs could have such things) or a later sibling.
There is no parent selector.

Is there a way to individually target multiple CSS classes at once? [duplicate]

This question already has answers here:
Is there a CSS selector by class prefix?
(4 answers)
combined multiple classes into one css rule
(3 answers)
Closed 4 years ago.
For instance, I have the following code in a .less file, and would like to simplify it. Each nav is an individual navigation point. When the user hovers over that nav point, I only want that particular nav point's background color to change. Not every single one of them.
.nav-1:hover {
background:#fc9426;
}
.nav-2:hover {
background:#fc9426;
}
.nav-3:hover {
background:#fc9426;
}
.nav-4:hover {
background:#fc9426;
}
.nav-5:hover {
background:#fc9426;
}
.nav-6:hover {
background:#fc9426;
}
.nav-7:hover {
background:#fc9426;
}
.nav-8:hover {
background:#fc9426;
}
.nav-9:hover {
background:#fc9426;
}
Use a comma.
.nav-1:hover,
.nav-2:hover,
.nav-3:hover {
color: #fc9426;
}
Although I don't have any markup to go off of, it looks like you could create a helper/modifier class instead of defining the same thing over and over again.
It might look something like this:
[class^="nav-"] {
margin: 1rem 0;
padding: 0 1rem;
min-height: 3rem;
color: #333;
font: 1rem/3rem Arial, sans-serif;
border-bottom: 1px solid black;
}
/**
* Utility/Modifier style properties that
* any nav could add to their base of styles.
*/
.nav-branded {
color: white;
background-color: #fc643c;
}
.nav-branded:hover {
background-color: hotpink;
}
/**
* These classes have styles specific to
* each class (acts like an ID but
* without the specificity).
*/
.nav-1 {
/* Waiting for some styles. */
}
.nav-2 {
border-bottom-width: 4px;
}
.nav-3 {
border-bottom-style: dashed;
}
<nav class="nav-1 nav-branded">Nav One</nav>
<nav class="nav-2">Nav Two</nav>
<nav class="nav-3 nav-branded">Nav Three</nav>
CSS classes are meant to be re-used so you don't have to define a bunch of different ones to get the same styling.
The point of classes is for a given property to apply to a variety of elements. So you should give each <nav> the same class.
<nav class='color-change'>
.
.
.
</nav>
Then in your CSS / LESS:
.color-change:hover {
background:#fc9426;
}
I think you imagine that you have a code like this
<div class="nav-1"> </div>
<div class="nav-2"> </div>
<div class="nav-3"> </div>
<div class="nav-4"> </div>
If so, you could simplify the code with a better advanced selector
[class*='nav-']{
background:#fc9426;
}
In this way, you will select the elements that in the 'class' attribute have in any part of the code the word 'nav-', which is the piece of the name of the class in common
In the case that in the HTML they have a father
<div class="nav">
<div class="nav-1"> </div>
<div class="nav-2"> </div>
<div class="nav-3"> </div>
<div class="nav-4"> </div>
</nav>
you can use this CSSs
.nav > div{}
.nav [class*='nav-']{}
.nav > div:nth-of-type(1){} /* the number of the son */
.nav > div:nth-of-type(2n){} /* all the pairs */
.nav > div:nth-of-type(2n+1){} /* all the odd */
If you can't change your markup to avoid the redundancy of selectors, you can use an attribute selector to catch all of those classes with a single specifier:
*[class*="nav-"]:hover, *[class*=" nav-"]:hover {
background:#fc9426;
}
The question was originally tagged with less, so if using less, you can also use recursion to generate those classes individually. This task is featured in the manual:
.generate-navs(9);
.generate-navs(#n, #i: 1) when (#i =< #n) {
.nav-#{i}:hover {
background:#fc9426;
}
.generate-navs(#n, (#i + 1));
}

scss nesting syntax: nest with parent adjoin class

I want to output:
.selector.another-selector .selector__block{some declaration}
but i want to nest it:
I am using & at the end so I can nest it under __block,
but how can I make it adjoin class with .selector?
code example:
.selector{
&__block{
// i want to put my .another-selector declaration here
.another-selector &{
//syntax issue
//need to make it .selector.another-selector .selector__block
}
}
thanks in advance.
If you nest your selector, then it has to be in the .selector__block context (&).
You have 2 solutions here :
You can repeat the first selector, as such:
.selector {
&__block {
...
.another-selector.selector & {
// Here `&` means `.selector__block`
}
}
}
You can nest differently:
.selector {
&__block {
...
}
&.another-selector &__block {
// Here `&` means `.selector`
}
}
Maybe the second solution is better since it respects the inception rule and is less dependent of the DOM structure.
BTW, you can also try https://www.sassmeister.com/ to play with your selectors
I would suggest that you don't nest BEM at all. Just go with plain declarations for two valid reasons.
1) error tracking nested BEM is hard, let say you get a class from devtools that is .hero__heading. That will not match anything in your code when doing a search. Now the example above is not that hard to figure out anyway but inheriting a project with nested structure is a pain. I suggest reading Harry Roberts article on code smells in css
2) nesting like this will often complicate when wanting to override with other classes like in your case.
Consider this code:
.selector {
background-color: deepskyblue;
}
.selector__block {
color: lightblue;
.another-selector & {
color: lightcoral;
}
}
#Dejan.S I'm not a big fan of BEM (but that's another rant ;-). If however you are using BEM I think nesting will help to illustrate the hierarchy and what to expect
SCSS:
.selector {
// selector styles
color: red;
// default selector block style
&__block { color: green; }
// selector variant selector block styles
&.foo &__block { color: blue; }
&.bar &__block { color: yellow; }
}
CSS Output:
.selector { color: red; }
.selector__block { color: green; }
.selector.foo .selector__block { color: blue; }
.selector.bar .selector__block { color: yellow; }
HTML:
<div class="selector">
Selector <!-- red -->
</div>
<div class="selector">
Selector <!-- red -->
<div class="selector__block">
Selector Block <!-- green -->
</div>
</div>
<div class="selector foo">
Selector <!-- red -->
<div class="selector__block">
Selector Foo Block <!-- blue -->
</div>
</div>
<div class="selector bar">
Selector <!-- red -->
<div class="selector__block">
Selector Bar Block <!-- yellow -->
</div>
</div>

Sass pattern for traversing up the tree

I have the following SASS structure
.entry {
//some styles here
.banner {
border:4px solid red;
.position {
display: inline-block;
}
}
}
And in html
<div class="entry">
<div class="banner>
<div class="position"></div>
</div>
</div>
Now I want to change the style of .banner and .position when an extra class is added to the entry.
<div class="entry team1">
<div class="banner>
<div class="position"></div>
</div>
</div>
This is a problem I have encountered lots of times and have never found a clean way to do it, the & operator or the #extend could be options but ideally I would like to group all the styles which have the same class.
Any suggestion on how I could write this pattern as efficiently as possible would be appreciated?
Well I would suggest something like that:
.entry {
.banner { /* defaults */ }
&.team1 {
.banner {
/* changes */
.position { /*changes */}
}
}
}
As far as I know, it is not possible to »traverse up the tree« in css, so it wont in scss either.
Another thing that comes to my mind is the #at-root what moves the rule to the root of the generated css. But all in all this will result in a »global« class definition, so I guess that is not what you want.

Resources