how to select root class variable into another class in css - css

<style>
:root product6 {
--width:435px;
}
:root .size1 {
--scale: 0.8;
}
:root .size2 {
--scale: 0.7;
}
.productDiv {transform:scale(--scale);}
</style>
<div class="product6 size1"></div>
This is working well if I give classes inside div class attr...showing my div scaled 0.8 and width 435px
But how can I select size1 class inside css syntax under stylesheet
.productDivResponsive {width:435px;transform:scale(???)}
Thanks.

Define your variables in root element (:root), so that they are available everywhere. Then define classes and ids, that use those variables in any way you see fit.
(If you want a narrower scope, you can also define your vars for another element. You do not necessarily have to use :root. Have a look at the special section in my example.)
/* define vars for everywhere, as everything inherits from root */
:root {
--width: 100px;
--height: 100px;
--scale-1: 0.8;
--scale-2: 0.6;
--scale-3: 0.4;
--c-green: #3d9970;
--c-red: #ff4136;
--c-blue: #0074d9;
}
/* define vars for a specific part of your page, overriding root in this example */
#special {
--c-green: #01FF70;
--c-red: #f012be;
--c-blue: #7fdbff;
border: 1px solid #ccc;
}
section {
margin: 10px;
}
main {
display: flex;
flex-flow: row wrap;
align-items: center;
justify-content: center;
}
.product {
width: var(--width);
height: var(--height);
box-shadow: inset 0 0 1em rgba(0, 0, 0, 0.4);
color: rgba(60, 60, 60, 0.7);
font-family: sans-serif;
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: center;
font-size: 24px;
font-weight: 700;
text-align: center;
background-image: linear-gradient(rgba(255, 255, 255, 0.4), rgba(0, 0, 0, 0.3))
}
.scale-1 {
transform: scale(var(--scale-1));
}
.scale-2 {
transform: scale(var(--scale-2));
}
.scale-3 {
transform: scale(var(--scale-3));
}
#product-2 {
background-color: var(--c-green);
}
#product-3 {
background-color: var(--c-red);
}
#product-4 {
background-color: var(--c-blue);
}
#product-5 {
background-color: var(--c-green);
}
#product-6 {
background-color: var(--c-red);
}
#product-7 {
background-color: var(--c-blue);
}
/* within scope of #special, colors are different: */
#product-10 {
background-color: var(--c-blue);
}
#product-11 {
background-color: var(--c-red);
}
#product-12 {
background-color: var(--c-green);
}
<main>
<section>
<div id="product-1" class="product">1</div>
<div id="product-2" class="product scale-1">2</div>
<div id="product-3" class="product scale-2">3</div>
<div id="product-4" class="product scale-3">4</div>
</section>
<section>
<div id="product-5" class="product scale-3">5</div>
<div id="product-6" class="product scale-2">6</div>
<div id="product-7" class="product scale-1">7</div>
<div id="product-8" class="product">8</div>
</section>
<section id="special">
<div id="product-9" class="product scale-2">9</div>
<div id="product-10" class="product scale-2">10</div>
<div id="product-11" class="product scale-2">11</div>
<div id="product-12" class="product scale-2">12</div>
</section>
</main>

This is working well if I give classes inside div class attr...showing my div scaled 0.8 and width 435px
The code provided cannot possibly work, it's syntactically erroneous.
But how can I select size1 class inside css syntax under stylesheet?
Addition of question mark was my edit.
CSS is static, hard coded, so just write it in just as you have with the rest of your CSS. I hope you are not asking how to dynamically manipulate CSS on the stylesheet because you need to grasp the advanced concepts dealing with CSS and working knowledge of JavaScript.
Demo
Note: Details are commented in demo
/*
Declare CSS variables
:root is the best selector to use because all descendants
will have access to them.
--=These are VALUES ONLY=--
They cannot be assigned to a selector directly
They can only be assigned to a property
propert: value is assigned to a selector
*/
:root {
--w435: 435px;
--scX070: 0.7;
--scX120: 1.2;
}
.box {
background: gold;
color: blue;
outline: 3px solid blue;
margin: 20px auto;
min-height: 30px;
/*
This is the proper syntax when assigning the value of a
CSS variable to a property
${selector} {${property}: var(--${CSSVar});}
.box { width: var(--w435); }
*/
width: var(--w435);
}
.size1 {
transform: scaleX(var(--scX070));
}
.size2 {
transform: scaleX(var(--scX120));
}
<div class='box'></div>
<div class="box size1"></div>
<div class="box size2"></div>

If I use this code I can make that I need...but I don't want to write classes twice...Problem is I want to use divs somewhere static somewhere responsive...
<style>
:root .product6 {
--width:435px;
}
:root .size1 {
--scale: 0.8;
}
:root .size2 {
--scale: 0.7;
}
.productDiv {transform:scale(--scale);}
#media (min-width: 1600px) {
:root {
--scale:0.8;
}
.productDivResponsive {transform:scale(var(--scale));}
}
#media (max-width: 1600px) and (min-width: 1360px) {
:root {
--scale:0.7;
}
.productDivResponsive {transform:scale(var(--scale));}
}
</style>
<div class="product6 productDiv"></div> <!-- This one static and scaling my div 0.8 -->
and want to make it responsive somewhere in my page with writing code something like that;
<div class="productDivResponsive"></div>
my productDivResponsive div must be scaled according to my media queries...
how can I remove repeating root class variables?
I hope I can explain what I need...Possible??

Related

Sass how to use ampersand within :not() pseudo class to mean not having a parent class?

I need add a condition "not parent class" to the code but it is not working.
Below is what I've tried:
.display-download-icon {
&:not(.media-2 &){ // if it does not has a parent with .media-2 class
&:hover {
.image-overlay {
display: block;
opacity: 1;
z-index: 2;
}
}
}
}
But it translates into the CSS below:
.display-download-icon:not(.media-2 .display-download-icon):hover .image-overlay {
display: block;
opacity: 1;
z-index: 2;
}
The HTML structure is:
<div class="media-2">
<div class="display-download-icon">
<div class="image-overlay"></div>
</div>
</div>
Can you help?
Thanks
To begin with, we have to get some things straight. You probably misunderstood this article with the somewhat unfortunate title. Although CSS has a child selector, it lacks the possibility to select parents. As SASS is only a more convenient way to write CSS, SASS cannot have such a thing either. This said, let's move on to your question.
If I understand you correctly, you want to have the hover effect on the image-overlay element only if it is not contained in an element with the class media-2.
If that's the case, then you will have to change your approach.
First, define the normal behaviour, i.e the one that is expected for all the elements except the ones with the .media-2 class. Then define a new rule for the .media-2 class children.
SASS
.display-download-icon {
display: block; /* Just for the demo */
height: 100px; /* Just for the demo */
width: 100%; /* Just for the demo */
border: 1px solid black; /* Just for the demo */
margin-bottom: 10px; /* Just for the demo */
> .image-overlay {
display: block;
opacity: 1;
z-index: 2;
height: 100%; /* Just for the demo */
width: 100%; /* Just for the demo */
&:hover {
background: red; /* Just for the demo */
}
}
}
.media-2 .display-download-icon > .image-overlay:hover {
background: none; /* Just for the demo */
}
Snippet
Check this snippet for the functionality
.display-download-icon {
display: block;
height: 100px;
width: 100%;
border: 1px solid black;
margin-bottom: 10px;
}
.display-download-icon > .image-overlay {
display: block;
opacity: 1;
z-index: 2;
height: 100%;
width: 100%;
}
.display-download-icon > .image-overlay:hover {
background: red;
}
.media-2 .display-download-icon > .image-overlay:hover {
background: none;
}
<div class="media-1">
<div class="display-download-icon">
<div class="image-overlay"></div>
</div>
</div>
<div class="media-2">
<div class="display-download-icon">
<div class="image-overlay"></div>
</div>
</div>
<div class="media-3">
<div class="display-download-icon">
<div class="image-overlay"></div>
</div>
</div>
I hope that you get the idea.
All the "&" does is act as an alias for the preceding parent selector, which is why you are getting the compiled output you are (because of the "&" after the .media-2 classname) . You just need to remove the last "&" and it will compile fine.
.display-download-icon {
&:not(.media-2){ // removed the "&"
&:hover {
.image-overlay {
display: block;
opacity: 1;
z-index: 2;
}
}
}
}
The above with compile to
.display-download-icon:not(.media-2):hover .image-overlay {
display: block;
opacity: 1;
z-index: 2;
}
But you can also remove some of that nesting as well to make it more readable
.display-download-icon:not(.media-2):hover {
.image-overlay {
display: block;
opacity: 1;
z-index: 2;
}
}
Which will compile to the same output.
Sadly, there's no such thing as a parent selector in CSS, so this isn't really a Sass ampersand issue as much as a core behaviour of CSS.
You'll need to write a dedicated rule like this:
/* base icon styling */
.display-download-icon {
...
}
/* separate rule for parent case */
div:not(.media-2) {
.display-download-icon {
&:hover {
.image-overlay {
display: block;
opacity: 1;
z-index: 2;
}
}
}
}

#mixin select a specific placeholder by using argument

I'm trying to use a mixin with an argument and inside a placeholder.
The idea is to use one line of code to select a specific placeholder in a class.
Actually, I don't know if there is another better way to do that, maybe with a function or other.
I'm learning Sass, so I'm trying to experiment.
HTML
<div class='wrap'>
<div class='box'></div>
<div class='box'></div>
</div>
SCSS
// VAR
$size-xs: 30px;
$size-s: 50px;
$size-m: 70px;
$color-1: orange;
$color-2: rgb(34,139,86);
#mixin box($val) {
%box-one {
width: $size-s;
height: $size-s;
background: $color-1;
margin: auto;
border-radius: 6px;
}
%box-two {
width: $size-s;
height: $size-s;
background: $color-2;
margin: auto;
border-radius: 6px;
}
.box {
#extend #{$val} !optional;
}
}
.wrap {
width: 100%;
height: 100px;
background: #f5f5f5;
display: flex;
justify-content: space-between;
#include box(box-one);
}
thank you!
Currently, your code is not working because your forgot to put a % before #{$val}:
.box {
#extend %#{$val} !optional;
}
Anyhow, it's not a good idea to put placeholder selectors inside a mixin because every time the mixin is called, you are creating new selectors. It means that for example if you add:
.randomSelector {
#include box(box-one);
}
You will get:
.wrap .box { ... }
.randomSelector .box { ... }
Instead of:
.randomSelector .box, .wrap .box { ... }
So I would recommend you to externalize %box-one and %box-two.
One last thing, if the only difference between these two classes is the background property, maybe using a single class regrouping the commons properties would be a better optimization:
.box {
width: $size-s;
height: $size-s;
margin: auto;
border-radius: 6px;
}
%box-one {
background: $color-1;
}
%box-two {
background: $color-2;
}
#mixin box($val) {
.box {
#extend %box-#{$val} !optional;
}
}
.wrap {
width: 100%;
height: 100px;
background: #f5f5f5;
display: flex;
justify-content: space-between;
#include box(one);
}
If you have more box styles you can even dynamically create the placeholders:
$boxStyles: (
one: $color-1,
two: $color-2
);
#each $box, $style in $boxStyles {
%box-#{$box} {
background: $style;
}
}

Is it possible to pass a class as parameter to a mixin in Stylus?

I’m trying to reduce some Stylus code using its mixins.
In some particular cases I need a class as a parameter. Let’s we’ve got:
.parent:hover .child
color: lighten(red, -25%)
.child
color red
I’d like to have a mixin which gets both classes as parameters.
I can’t find a way from the docs. ((
You can achieve this with interpolation: http://stylus-lang.com/docs/interpolation.html
Here's an example codepen: https://codepen.io/webdevdani/pen/POVLpr
Code example from codepen:
/* Stylus */
.box {
height: 2rem;
width: #height;
background-color: blue;
padding: 1rem;
}
.red-box {
background-color: red;
}
$blockColor(parentClass, childClass) {
{parentClass} {
background-color: green;
{childClass} {
background-color: yellow;
}
}
}
$blockColor('.box', '.red-box');
<div class="box">
<div class="box red-box"></div>
</div>

css variables - declare variable if not already defined

I have a project which is split up into the parent app, and several reusable child components in separate repositories. I'd like to define default CSS variables in these child components, which can be overridden by the parent app, however I can't find the right syntax for this. Here's what I've tried:
/* parent */
:root {
--color: blue;
}
/* child */
:root {
--color: var(--color, green);
}
.test {
width: 200px;
height: 200px;
background: var(--color, red);
}
https://codepen.io/daviestar/pen/brModx
The color should be blue, but when the child :root is defined, the color is actually red, at least in Chrome.
Is there a correct approach for this? In SASS you can add a !default flag to your child variables which basically means 'declare if it's not already declared'.
CSS stands for cascading style sheets,
so you cannot override anything by a parent...
The only way is to create a stronger rule.
look at .c1 and .p1
.parent {
--background: red;
}
.child {
--size: 30px;
--background: green; /* this wins */
background-color: var(--background);
width: var(--size);
height: var(--size);
}
.p1 .c1 {
--background: red; /* this wins */
}
.c1 {
--size: 30px;
--background: green;
background-color: var(--background);
width: var(--size);
height: var(--size);
}
<div class="parent">
<div class="child"></div>
</div>
<hr />
<div class="p1">
<div class="c1"></div>
</div>
Thanks to #Hitmands hint I have a neat solution:
/* parent */
html:root { /* <--- be more specific than :root in your parent app */
--color: blue;
}
/* child */
:root {
--color: green;
}
.test {
width: 200px;
height: 200px;
background: var(--color);
}
I would suggest an approach by aliasing the variables in the component and using "parent" or root variables as main value while local value is by !default.
.parent {
--background: red;
}
.child {
--child_size: var(--size, 30px); /* !default with alias */
--child_background: var(--background, green); /* !default with alias */
background-color: var(--child_background);
width: var(--child_size);
height: var(--child_size);
}
<div class="parent">
<div class="child"></div>
</div>
<hr>
<div class="child"></div>

Is there a way to reproduce currentColor with var(--current-color)?

I don't use currentColor very often but when I do, it's extremely useful.
So I've been a little excited about the arrival of CSS Variables.
Let's take a traffic light.
N.B. Please take it on trust from me that Japanese traffic lights go red to amber to blue. I know it's hard to believe. I know the blue light looks sort-of green. But it isn't, it's blue.
div {
float: left;
width: 200px;
}
div div {
float: none;
}
.top {
color: rgb(255,0,0);
}
.middle {
color: rgb(255,227,0);
}
.bottom {
color: rgb(63,255,63);
}
.jp .bottom {
color: rgb(0,255,191);
}
.light {
text-align: center;
}
.light::before {
content: '';
display: block;
margin: 6px auto 0;
width: 25px;
height: 25px;
border-radius: 15px;
background-color: currentColor;
}
<div class="uk">
<h2>UK Traffic Lights</h2>
<div class="top light">Red</div>
<div class="middle light">Amber</div>
<div class="bottom light">Green</div>
</div>
<div class="jp">
<h2>JP Traffic Lights</h2>
<div class="top light">Red</div>
<div class="middle light">Amber</div>
<div class="bottom light">Blue</div>
</div>
Now, the clever thing about
background-color: currentColor;
is that it just reads whatever the current value for color is and uses that.
By contrast...
background-color: var(--current-color);
That can't reference the current value of another style declaration, can it?
So, you'd need to set up 4 variables (just like you need to declare color: 4 times in the styles above):
.top {
--color-top: rgb(255,0,0);
}
.middle {
--color-middle: rgb(255,227,0);
}
.bottom {
--color-bottom: rgb(63,255,63);
}
.jp .bottom {
--color-bottom-jp: rgb(0,255,191);
}
And then... you need to reference each of those different variables later on. Which means a different background-color declaration for each variable:
.top::before {
color: var(--color-top);
background-color: var(--color-top);
}
.middle::before {
color: var(--color-middle);
background-color: var(--color-middle);
}
.bottom::before {
color: var(--color-bottom);
background-color: var(--color-bottom);
}
.jp .bottom::before {
color: var(--color-bottom-jp);
background-color: var(--color-bottom-jp);
}
Really?!
That can't be right. Have I missed something?
Is there no way to reproduce currentColor with var(--current-color) ?
Is there no way for CSS variables to represent the current value of another style declaration?
Actually, you can set a CSS custom property instead of setting directly the color property, and use it for color and background-color.
/* Set global variable inside the :root scop */
:root {
--color-top: rgb(255,0,0);
}
div {
float: left;
width: 200px;
}
div div {
float: none;
}
/* Set the local --color variable, according to your need */
.top {
--color: var(--color-top);
}
.middle {
--color: rgb(255,227,0);
}
.bottom {
--color: rgb(63,255,63);
}
.jp .bottom {
--color: rgb(0,255,191);
}
.light {
color: var(--color);
text-align: center;
}
.light::before {
content: '';
display: block;
margin: 6px auto 0;
width: 45px;
height: 45px;
border-radius: 15px;
background-color: var(--color);
}
<div class="uk">
<h2>UK Traffic Lights</h2>
<div class="top light">Red</div>
<div class="middle light">Amber</div>
<div class="bottom light">Green</div>
</div>
<div class="jp">
<h2>JP Traffic Lights</h2>
<div class="top light">Red</div>
<div class="middle light">Amber</div>
<div class="bottom light">Blue</div>
</div>
I do not really understand why you are not using background-color: currentColor, because it works well in your own example.
If you are using SASS (which is compiled into css), then you can use SASS variables. The code will look like :
$font-stack: Helvetica;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}
more informations on the SASS official website

Resources