SASS: Conditional values of CSS property based on that if an element with certain value of the same property has been present already in the page - css

I want to have different values of a css property (I am using SASS), based on that whether a element with a certain property's value '$additionalNavHeight' is present on the page. In some pages there is no such element, in other - there is. I wrote a SASS mixin:
#mixin top-position($navHeight, $additionalNavHeight)
{
#if $additionalNavHeight == true {
.loadingAnimation {
top: $navHeight + $additionalNavHeight;
}
}
#else {
.loadingAnimation {
top: $navHeight;
}
}
}
And I included the mixin in the selector:
#include top-position($navHeight, $additionalNavHeight);
I thought this should change the value of the property 'top' of the element with the class 'loadingAnimation', based on that if in the page already is present the element with the value of its 'top' property '$additionalNavHeight'. The compiler doesn't show any error, but the code doesn't change anything. What am I doing wrong? Any help would be very appreciated.

Тhe simplest solution. You must check with JavaScript if element exists or not
and to apply the second class to element. In the second case (element existing)
you must add adittionnal height. In this case the mixin is redundant.
.loadingAnimation {
top: $navHeight;
}
.loadingAnimation.additinnalHeight {
top: $navHeight + $additionalNavHeight;
}
Here is example jsfiffle:
https://jsfiddle.net/ra9r8rk8/
In this case element will receive class newClass when the first div exists. (the element)
Edit: This is second improved solution. In fact there is no need for regular expression. We can just use classList:
https://jsfiddle.net/ra9r8rk8/1/

Related

How I exclude more than one element with CSS selector group? [duplicate]

I'm trying to select input elements of all types except radio and checkbox.
Many people have shown that you can put multiple arguments in :not, but using type doesn't seem to work anyway I try it.
form input:not([type="radio"], [type="checkbox"]) {
/* css here */
}
Any ideas?
Why :not just use two :not:
input:not([type="radio"]):not([type="checkbox"])
Yes, it is intentional
If you're using SASS in your project, I've built this mixin to make it work the way we all want it to:
#mixin not($ignorList...) {
//if only a single value given
#if (length($ignorList) == 1){
//it is probably a list variable so set ignore list to the variable
$ignorList: nth($ignorList,1);
}
//set up an empty $notOutput variable
$notOutput: '';
//for each item in the list
#each $not in $ignorList {
//generate a :not([ignored_item]) segment for each item in the ignore list and put them back to back
$notOutput: $notOutput + ':not(#{$not})';
}
//output the full :not() rule including all ignored items
&#{$notOutput} {
#content;
}
}
it can be used in 2 ways:
Option 1: list the ignored items inline
input {
/*non-ignored styling goes here*/
#include not('[type="radio"]','[type="checkbox"]'){
/*ignored styling goes here*/
}
}
Option 2: list the ignored items in a variable first
$ignoredItems:
'[type="radio"]',
'[type="checkbox"]'
;
input {
/*non-ignored styling goes here*/
#include not($ignoredItems){
/*ignored styling goes here*/
}
}
Outputted CSS for either option
input {
/*non-ignored styling goes here*/
}
input:not([type="radio"]):not([type="checkbox"]) {
/*ignored styling goes here*/
}
Starting from CSS Selectors 4 using multiple arguments in the :not selector becomes possible (see here).
In CSS3, the :not selector only allows 1 selector as an argument. In level 4 selectors, it can take a selector list as an argument.
Example:
/* In this example, all p elements will be red, except for
the first child and the ones with the class special. */
p:not(:first-child, .special) {
color: red;
}
Unfortunately, browser support is somewhat new.
I was having some trouble with this, and the "X:not():not()" method wasn't working for me.
I ended up resorting to this strategy:
INPUT {
/* styles */
}
INPUT[type="radio"], INPUT[type="checkbox"] {
/* styles that reset previous styles */
}
It's not nearly as fun, but it worked for me when :not() was being pugnacious. It's not ideal, but it's solid.
If you install the "cssnext" Post CSS plugin, then you can safely start using the syntax that you want to use right now.
Using cssnext will turn this:
input:not([type="radio"], [type="checkbox"]) {
/* css here */
}
Into this:
input:not([type="radio"]):not([type="checkbox"]) {
/* css here */
}
https://cssnext.github.io/features/#not-pseudo-class

When using CSS Variables (CSS Custom Properties) why is the setting syntax and the getting syntax different?

When using CSS Variables (CSS Custom Properties) why is the setting syntax and the getting syntax different?
If I wish to set a value for --my-custom-width, I will use:
:root {
--my-custom-width: 120px;
}
And if I wish to get a value for --my-custom-width, I will use a var() function to retrieve the same value:
.my-div {
width: var(--my-custom-width);
}
Why do we not simply write:
.my-div {
width: --my-custom-width;
}
Having been using CSS Custom Properties since late 2017, I've finally understood properly what they really are and why the var() function is necessary...
They are not (as they so often appear to be) variables intended to directly represent CSS values.
CSS Custom Properties are exactly what they say they are - they are new CSS properties which have not (yet) been assigned values.
In CSS, an example of something which really does approximate a variable representing a value is currentColor.
We see currentColor representing a value, here:
.my-div {
border: 1px dashed currentColor;
}
But CSS Custom Properties are not CSS variables which stand in for values like currentColor, .
Instead, CSS Custom Properties are newly invented, named, null-value-properties...
... and those newly-invented, named, null-value-properties are completely re-usable. Just like width, height, color etc. they may have values set and reset in different contexts.
E.g.
/* My custom property is --my-custom-width but I want this
property to hold different values in different contexts */
.left-two-thirds-of-page {
--my-custom-width: 120px;
}
.right-third-of-page {
--my-custom-width: 60px;
}
.my-div {
width: var(--my-custom-width);
}
That's why the var() function is necessary - it's not delivering "the custom property" - it's extracting the value that custom property is currently holding and then delivering that value.
Further Thoughts:
In hindsight, I wonder if the whole name-value relationship wouldn't have been a little clearer if CSS Custom Properties had been called:
CSS Custom Property Names
and the corresponding function had been called:
value()
so the syntax would have been written and read out as:
value(--my-custom-property-name)
By extension we could use the value() function (or var() function) not just on custom properties but on any property.
For instance:
width: value(height);

Parent Selector nested inside &:hover

I am using the Less parent selector to shorten my selectors:
.module-name {
// styles go here
&__sub-module-1 {
//styles go here
}
}
Now my problem is how to continue to use the parent selector for adding the module-name inside a nested :hover statement. E.g. on hover of sub-module-1 I want to change something in sub-module-2. Inside the &:hover statement, what does the parent selector refer to?
.module-name {
&__sub-module1 {
&:hover {
&__sub-module2 {
// on hover of .module-name__sub-module1 change something in .module-name__sub-module2
}
}
}
}
If i write it like this it works, but it defeats the purpose of using the parent selector to automatically fill in the name of the module:
.module-name {
&__sub-module1 {
&:hover {
.module-name__sub-module2 {
// on hover of .module-name__sub-module1 change something in .module-name__sub-module2
}
}
}
}
I hope I could adequately express my problem; any help is appreciated.
The parent selector (&) will always refer to the full parent based on the level at which you are. For example at the first level of nesting, & refers to .module-name. In the second level, it refers to .module-name__sub-module1 and in the third level, it refers to .module-name__sub-module1:hover.
Extract from Less Website: Note that & represents all parent selectors (not just the nearest ancestor or the overall root ancestor)
The emphasised part in the above statement is my inclusion based on the context
For this particular case, you could assign the module-name to a variable and use selector interpolation like below to form the selectors.
The variable value would never change unlike the parent selector (&) irrespective of how many levels of nesting you have and at which level of nesting you are using it.
#module-name: mod-name;
.#{module-name} {
&__sub-module1 {
&:hover {
& .#{module-name}__sub-module2 {
// on hover of .module-name__sub-module1 change something in .module-name__sub-module2
color: blue;
}
}
}
}

How to know if element height or width was set in javascript/css?

Is there any way to know if an element height or width was set (not auto) in javascript/css ?
elm.style.height will only return a value if the height is defined inside the element attribute list : <div style='height:200px' .... ></div>, otherwise it will always return an empty string even if you define the height inside a style tag or a css file : .myElmCss{height:200px}.
On the other hand, using window.getComputedStyle() or elm.currentStyle will always return a value even if no height was defined neither inside the element attribute list nor in a css file/style tag.
Thanks.
Check this post How do you read CSS rule values with JavaScript?
To do what you're looking for it appears to be a matter of iterating over the stylesheets to find declared properties. You would probably also cross reference with inline styles like you mentioned in your question.
from #InsDel's post:
function getStyle(className) {
var classes = document.styleSheets[0].rules || document.styleSheets[0].cssRules
for(var x=0;x<classes.length;x++) {
if(classes[x].selectorText==className) {
(classes[x].cssText) ? alert(classes[x].cssText) : alert(classes[x].style.cssText);
}
}
}

Can the :not() pseudo-class have multiple arguments?

I'm trying to select input elements of all types except radio and checkbox.
Many people have shown that you can put multiple arguments in :not, but using type doesn't seem to work anyway I try it.
form input:not([type="radio"], [type="checkbox"]) {
/* css here */
}
Any ideas?
Why :not just use two :not:
input:not([type="radio"]):not([type="checkbox"])
Yes, it is intentional
If you're using SASS in your project, I've built this mixin to make it work the way we all want it to:
#mixin not($ignorList...) {
//if only a single value given
#if (length($ignorList) == 1){
//it is probably a list variable so set ignore list to the variable
$ignorList: nth($ignorList,1);
}
//set up an empty $notOutput variable
$notOutput: '';
//for each item in the list
#each $not in $ignorList {
//generate a :not([ignored_item]) segment for each item in the ignore list and put them back to back
$notOutput: $notOutput + ':not(#{$not})';
}
//output the full :not() rule including all ignored items
&#{$notOutput} {
#content;
}
}
it can be used in 2 ways:
Option 1: list the ignored items inline
input {
/*non-ignored styling goes here*/
#include not('[type="radio"]','[type="checkbox"]'){
/*ignored styling goes here*/
}
}
Option 2: list the ignored items in a variable first
$ignoredItems:
'[type="radio"]',
'[type="checkbox"]'
;
input {
/*non-ignored styling goes here*/
#include not($ignoredItems){
/*ignored styling goes here*/
}
}
Outputted CSS for either option
input {
/*non-ignored styling goes here*/
}
input:not([type="radio"]):not([type="checkbox"]) {
/*ignored styling goes here*/
}
Starting from CSS Selectors 4 using multiple arguments in the :not selector becomes possible (see here).
In CSS3, the :not selector only allows 1 selector as an argument. In level 4 selectors, it can take a selector list as an argument.
Example:
/* In this example, all p elements will be red, except for
the first child and the ones with the class special. */
p:not(:first-child, .special) {
color: red;
}
Unfortunately, browser support is somewhat new.
I was having some trouble with this, and the "X:not():not()" method wasn't working for me.
I ended up resorting to this strategy:
INPUT {
/* styles */
}
INPUT[type="radio"], INPUT[type="checkbox"] {
/* styles that reset previous styles */
}
It's not nearly as fun, but it worked for me when :not() was being pugnacious. It's not ideal, but it's solid.
If you install the "cssnext" Post CSS plugin, then you can safely start using the syntax that you want to use right now.
Using cssnext will turn this:
input:not([type="radio"], [type="checkbox"]) {
/* css here */
}
Into this:
input:not([type="radio"]):not([type="checkbox"]) {
/* css here */
}
https://cssnext.github.io/features/#not-pseudo-class

Resources