How do I nest attribute selector under :host-context? - css

Using LESS pre-processor along with shadow-dom for theming support of individual components. I have also attempted nesting :host-context and :host selectors to no avail.
:host-context(.dark) {
#import (multiple) 'variables/dark-theme';
.dropdown;
}
:host-context(.light) {
#import (multiple) 'variables/light-theme';
.dropdown;
}
.dropdown() {
//some component styles here
&:disabled {
background-color: #disabled-bg;
color: #disabled-color;
.dropDownListSelect {
cursor: not-allowed;
}
}
}

This is a result of my own ignorance with Shadow-DOM as it is still somewhat new to me. I was able to accomplish this by using the &:host selector.
:host-context(.dark) {
#import (multiple) 'variables/dark-theme';
.dropdown;
}
:host-context(.light) {
#import (multiple) 'variables/light-theme';
.dropdown;
}
.dropdown() {
//some component styles here
&:host([disabled]) {
background-color: #disabled-bg;
color: #disabled-color;
.dropDownListSelect {
cursor: not-allowed;
}
}
}

Related

LESS - Is there a way to group styles applied to a certain selector together and then apply it in another file?

Let's say I have a LESS file like this:
.wrapper-1 {
.textbox { // styles }
.textbox::placeholder { // styles }
.checkbox { // styles }
.button { // styles }
.some + other > complicated.selector::here { // styles }
}
Now, say I want to apply the styles within .wrapper-1 to another file for .wrapper-2 without having repeat all the styles again.
I want to essentially achieve this without having to repeat all the styles again.
.wrapper-2 {
.textbox { // styles }
.textbox::placeholder { // styles }
.checkbox { // styles }
.button { // styles }
.some + other > complicated.selector::here { // styles }
}
I started by creating a common file like and extracting selectors into their own variables like so:
#textbox: ~'.textbox';
#textbox-placeholder: ~'.textbox::placeholder';
#checkbox: ~'.checkbox';
#button: ~'.button';
#someOtherComplicatedSelector: ~'.some + other > complicated.selector::here';
#{textbox} { // styles }
#{textbox-placeholder} { // styles }
#{checkbox} { // styles }
#{button} { // styles }
#{someOtherComplicatedSelector} { // styles }
But how do I then apply those "variables" into the proper place I want them to be? I essentially want something like this (obviously, the syntax isn't right):
.wrapper-1 {
#{textbox}
#{textbox-placeholder}
#{checkbox}
#{button}
#{someOtherComplicatedSelector}
}
and
.wrapper-2 {
#{textbox}
#{textbox-placeholder}
#{checkbox}
#{button}
#{someOtherComplicatedSelector}
}
In essence, is there a way to bundle/group styles and selectors together to be applied within other selectors?

Add attribute to all CSS rules except some

I need to add an attribute [dir=ltr] to all the rules of a big CSS file except for some ones.
Source CSS:
.rule-1 {
color:black
}
.rule-2 {
color: yellow
}
.rule-3 { /* exclude */
color: blue
}
.rule-4 {
color: red
}
Target CSS:
[dir=ltr] .rule-1 {
color:black
}
[dir=ltr] .rule-2 {
color: yellow
}
.rule-3 {
color: blue
}
[dir=ltr] .rule-4 {
color: red
}
Maybe a CSS postprocessor is needed here.
Try using the css :not() attribute, example below:
[dir=ltr]:not(.rule-3) {
//..
}
You can learn more about this attribute and what it does here
The issue was solved using the PostCSS plugin postcss-prefix-selector.
postcss.config.js
module.exports = {
plugins: {
"postcss-prefix-selector": {
prefix: '[dir=ltr]', exclude: [/.rule-3(?![\w])/]
}
}
}

Gulp SCSS Color Variables to css

I have a scss file with over 20 lines of color variables. I want to create a css file with these variables to have one class for color and class for background-color.
Example:
from scss variable
$color-red: #FF0000;
to css
.color-red { color:#FF0000; }
.bg-color-red { background-color:#FF0000; }
Is there any Gulp plugin that allows me to do it?
any recomendation accepted but i need to do it with gulp if it is possible.
As #chriskirknielsen suggested, sass maps and the #each rule is a good choice here. This is the first time I have used these concepts but this works in my testing.
Your colors.scss file would look like this:
$colors: ("color-red": "#FF0000", "color-green": "#00ff40"); // etc.
#each $color, $value in $colors {
.#{$color} {
color: #{$value};
}
.bg-#{$color} {
background-color: #{$value};
}
}
The gulp-sass output in colors.css is:
.color-red {
color: #FF0000; }
.bg-color-red {
background-color: #FF0000; }
.color-green {
color: #00ff40; }
.bg-color-green {
background-color: #00ff40; }
See https://sass-lang.com/documentation/values/maps#do-something-for-every-pair

The Sass ampersand and attribute selectors

I want to create a sass file that the selectors will be attribute selectors.
When I work with class selectors, in most of the cases I will do
.parent {
&-child {
}
}
which gives me the following css: .parent-child {}.
I want to achieve the same thing with attribute selectors:
[data-parent] {
&-child {
}
}
which I want to become: [data-parent-child] {}
someone knows how to achieve this? thanks.
You can use this mixin as a workaround to get the desired result.
#mixin child-attribute($child) {
$string: inspect(&);
$original: str-slice($string, 3, -4);
#at-root #{ selector-replace(&, &, "[#{$original}#{$child}]" ) } {
#content;
}
}
The code simply does the following
$string variable is responsible for turning the parent selector to a string using the inspect function
$original variable is responsible for getting the text content of the $string variable i.e the value 'data-parent' from '([data-parent])'
selector-replace function then replaces the parent selector with the concatenation of the $original variable and child variable
When used in the following ways
[data-parent] {
#include child-attribute('-child') {
color: green;
}
}
The css output
[data-parent-child] {
color: green;
}
Depending on what you want to achieve, it can also be used like this
[grandparent] {
#include child-attribute('-parent') {
color: white;
#include child-attribute('-child') {
color: blue;
}
}
}
Which generates the following css
[grandparent-parent] {
color: white;
}
[grandparent-parent-child] {
color: blue;
}
Hope this helps you
You can create mixin that will set styles for elements with data attribytes.
Scss:
#mixin data($name) {
[data-#{$name}] {
#content;
}
}
* {
#include data('lol') {
color: red;
};
}
Css output:
* [data-lol] {
color: red;
}
DEMO
I would go down a slightly different route of having a class on your elements that contain the data attributes.
<div class="data-obj" data-parent="true"></div>
<div class="data-obj" data-parent-child="true"></div>
then in your SASS do
.data-obj {
...
&[data-parent] { ... }
&[data-parent-child] { ... }
}

How to change a class format based on body's class with SCSS?

I am making a web app that is used in three (or more) different contexts, and I want each context to have a different color scheme. However, I don't want to have to maintain three different stylesheets when all that changes is colors, typically.
For instance, suppose the themes are red, blue, and orange. One of my stylesheets describes the link colors:
a {
color: $some_color;
}
I want to split this based on the class applied to the body:
body.style1 {
a {
color: $red;
}
}
body.style2 {
a {
color: $blue;
}
}
body.style3 {
a {
color: $orange;
}
}
You can see how this gets unwieldy pretty quickly if you're changing the style for lots of elements. Is there a way to do this more like this?
a {
&closest:body.style1 {
color: $red
}
&closest:body.style2 {
color: $blue;
}
&closest:body.style3 {
color: $orange;
}
}
This way I can code my scss in a clearer, more maintainable way.
It appers you don't have to have the & first, so this works (at least in 3.2.10):
a {
body.style1 & {
color: $red
}
body.style2 & {
color: $blue;
}
body.style3 &{
color: $orange;
}
}
This is what I prefer. Define a mixin like body-style :
#mixin body-style($style, $map) {
body.#{$style} & {
#each $property, $value in $map {
#{$property}: $value;
}
}
}
Then use this for every tag by passing $style as style class of body and $map as map of css keys and values.
a {
#include body-style(style1, (
color: red,
background: white
)
);
}
It will return :
body.style1 a {
color: red;
background: white;
}

Resources