check if the parent has a specific class on it - sass

This is the usual list where one of the items is .open
for this I want to check if the parent (in this case is .item but its not relevant i think) has a specific class.
I've tried > but it doesnt seem to work.
Essentially how to put this:
&.open .info {
display: none;
}
&.open .inner-info {
display: flex;
}
inside of the their specific classes:
.info {
display: flex;
/* some other stuff */
}
.inner-info {
display: none;
/* some other stuff */
}
all of this is inside an .item{} block
So how do i have it so that i only have two blocks inside the .item{}?

It seems overkill to me, but you can use a hacky way to do that using a mixin and various functions. Please note that this will work for your specific example but probably not for something else.
I used the helper functions str-to-list and nth-delete, which are not native to SASS.
#mixin parentWithClass($class) {
$parent: nth-delete(str-to-list(#{&}), -1);
#at-root #{selector.replace(&, $parent, #{$parent}#{$class})} {
#content;
}
}
.item {
.inner {
color: blue;
#include parentWithClass(".open") {
color: orange;
}
}
.inner-info {
color: red;
#include parentWithClass(".open") {
color: grey;
}
}
}
You can also nest -info in inner.

Related

How to prefix SASS blocks with a specific scope ID via mixin

Looking to be able to add the app scope id to my sass files when we have multiple apps reusing class names.
That way I can have the following definition:
$app-scope-id: 'appOne';
And then write my SCSS in that app
.blockName{
background: blue;
&__element{
color: orange;
}
}
And call a mixin or something else to just go
#include prefixMixin(){
.blockName{
background: blue;
&__element{
color: orange;
}
}
}
And that render out css like:
.appOne-blockName{ background: blue; }
.appOne-blockName__element{ color: orange }
I'm aware I can use interpolation at the beginning of my block, but was hoping I could keep it cleaner with just a mixin call where necessary and only call it once for an entire SASS file if I wanted.
I don't think it's possible to do what you want with SASS. You could maybe do something like this:
$app-scope-id: 'appOne';
#mixin prefix($selectorType: ".") {
#at-root {
#{$selectorType}#{$app-scope-id}-#{&} {
#content;
}
}
}
blockName {
#include prefix() {
background: blue;
&__element{
color: orange;
}
}
}
Which compiles as:
.appOne-blockName { background: blue; }
.appOne-blockName__element { color: orange; }
But you would still need to include it for each selector that needs the prefix. I'm not sure this can be called "clean" either.

SASS select class that was chained to parent

I have the following HTML <div class="parent green"></div>
The green class may or may not be added. It is dynamic. It may also be another name.
In SASS how do I give properties to a .child element of parent when class green is chained to it?
I tried:
.parent {
.child {
.green & {
color: green;
}
}
}
It doesn't work.
I also tried the following which works but I am looking for something similar to the sass above. The code will become repeatable below because I have to add child each time for every dynamic class.
.parent {
&.green {
.child {
color: green;
}
}
}
I'm trying to get a structure like this if possible with sass:
.parent {
.child {
.green & { /* when .parent.green */
color: green;
}
.blue & { /* when .parent.blue */
color: blue;
}
.text-align-right & { /* when .parent.text-align-right */
text-align: right;
}
etc...
}
}
& is treated as parent selector reference in Sass, because of this your code doesn't work since it refers wrong selector.
Use of & directly will not help here, but your goal can be achieved by using mixins, for example:
#mixin child($class) {
&.#{$class} {
.child {
#content;
}
}
}
.parent {
#include child(green) {
color: green;
}
#include child(blue) {
color: blue;
}
#include child(text-align-right) {
text-align: right;
}
}
This piece of code produces result that you want to get, you can check in by yourself on sassmeister.

How can I target the syntactical parent when using the ampersand?

I'm trying to remove some duplication in my scss selector.
.container {
.operation {
color: green;
}
.row.is-active &,
.row:hover & {
.operation {
color: inherit;
}
}
}
I tried rewriting it like this:
.container {
.operation {
color: green;
}
.row & {
&.is-active, &:hover {
.operation {
color: inherit;
}
}
}
}
However, this causes .is-active to be applied to .container instead of .row
How can I target the syntactical parent when using the ampersand ?
I took some time to answer the question again, as I mis-understood it initially. Unfortunately there is absolutely no way possible to do this in SASS at the moment. Even when trying to make use of the more advanced SASS functions to manipulate selectors and strings it is not possible.
There is some Good News
It is possible to do using Stylus.
I have created a live Example on codepen.
// Stylus - not SASS
.container {
.operation {
color: green;
}
.row {
^[-1..-1]:is-active ^[0], ^[-1..-1]:hover ^[0] {
.operation {
color: inherit;
}
}
}
}
I hope this helps you in some way, at the very least it might provide you with an option, but unfortunately SASS cannot achieve what you are attempting.

Using parent classes [duplicate]

This question already has an answer here:
SASS Replicating nested selector
(1 answer)
Closed 7 years ago.
Ive tried searching for an answer, but I feel like I'm asking the wrong questions.
I'm trying to create a "base parent" class that I can use to split up my rules nicely and across multiple files. The structure of the parent would be something like this:
.parent {
.child {
//some rules here
}
I then want to be able to import that parent and child class to help define further elements (using faux-syntax here)
#[custom class name]:
.parent {
//some rules
.child {
color: #000
}
Then, using my custom class name, I can specify this as the parent of another selector, like:
#[custom class name] {
.grand-child {
background-color: #fff;
}
}
This would generate out the following rule
.parent .child .grand-child {
color: #000;
background-color: #fff;
}
One way of doing this could be to create a mixin that uses the #content directive, like so:
#mixin selectors {
.parent {
.child {
#content;
}
}
}
Then, any time you want to nest something under .parent .child, you would write:
#include selectors {
.grand-child {
color: #000;
}
}
Which would result in the following CSS output:
.parent .child .grand-child {
color: #000;
}
You could always make use of the & selector.
If .grand-child is in another file, you could do something like this:
.grand-child{
.parent .child & {
color: #000;
}
}
this will compile to
.parent .child .grand-child{
color: #000;
}
Or are maybe you are also looking for the #extend possibility?
where you would add
.grand-child{
#extend .parent .child;
color: #000
}
This would get the style from .parent .child and add it to the grand-child, but only the styling, it will not change the selector above.

SASS: create name that is unique per-mixin?

I'm creating a mixin called static() that is used inside another mixin to separate the static properties out into placeholders, so that those properties aren't repeated in the output every time a mixin is used. Here's how you would use it in a mixin called button(), for example:
#mixin button($color) {
#include static('button') {
border: 1px solid;
border-radius: 5px;
padding: .25em .5em;
&:hover {
cursor: pointer;
}
}
background-color: $color;
&:hover {
background-color: mix(black, $color, 15%;
}
}
Here's the code for the static() mixin:
#mixin static($mixin-name, $extend: true) {
// set global $Placeholder-Selectors if it doesn't already exist
$Placeholder-Selectors: () !global !default;
$selector: map-get($Placeholder-Selectors, $mixin-name);
#if $extend == true {
#if $selector == null {
$selector: unique-id();
$Placeholder-Selectors: map-merge($Placeholder-Selectors, ($mixin-name: $selector)) !global;
#at-root %#{$selector} {
#include static($mixin-name, false) {
#content;
};
}
}
#extend %#{$selector};
} #else {
#content;
}
}
The only purpose of the variable $mixin-name is to make sure the declarations of the created placeholder are not overwritten by another placeholder of the same name. My assumption is that the best way to ensure this is to use the name of the mixin itself for the $Placeholder-Selectors' key (since this will be unique to the mixin).
Question:
If that assumption is correct, I don't want to have to type out the name of the mixin I'm using (as in "#include static('button')")...so, in the static() mixin, is there a way to dynamically determine the name of the mixin that static() is being used inside?
Or, is there another way to ensure a placeholder that is unique per-mixin?
No. Sass does not have a way to get any of the names of the mixins used.
That said, you're over-engineering. All you need to do is setup your extend selector outside of the mixin.
%common-button-styles {
border: 1px solid;
border-radius: 5px;
padding: .25em .5em;
&:hover {
cursor: pointer;
}
}
#mixin button($color) {
color: $color;
#extend %common-button-styles;
&:hover {
background-color: mix(black, $color, 15%);
}
}
If you're jumping through all of these hoops in an attempt to avoid creating duplicate extend only selectors via multiple imports, what you're looking for is called import once. If you're a Compass user, 1.0 includes an extension by default that does this. If not, a quick search will show you a few different ways of implementing such a feature.

Resources