My JS code sets a variable on the page:
if (error) {
document.querySelector('body')?.style.setProperty('--pickererror', `'${ error }'`);
}
My SCSS code uses that variable for some content:
$error: var(--pickererror);
// ERROR MESSAGE
.picker-toolbar::before {
content: $error;
color: red;
padding: 5px 35px 0px 35px;
text-align: center;
}
.picker-toolbar {
#if str-length($error) > 0 {
order: 1 !important;
}
}
The ::before section works completely. However the #if clause executes even if there is no error, and the .picker-toolbar is always at order: 1.
I have checked that --pickererror is not present when there's no JS error. I've tried any number of permutations, such as
Putting the #if line before the .picker-toolbar line
Simply using #if $error
Using #if var(--pickererror) in place of the $error variable.
How do I make this work?
What if you remove the logic from your stylesheet entirely, and instead rely on the dynamic property value from your JavaScript?
For example:
body {
--pickererror: 0; // Default value for the "order" property
}
If your JavaScript detects an error, the --pickererror is given a value of 1 !important;
if (error) {
document.querySelector('body').style.setProperty('--pickererror', '1', 'important');
}
And in your stylesheet, you only need a single rule that changes the order if the JavaScript says so.
.picker-toolbar {
order: var(--pickererror, 0); // Defaults to "0" also if the variable doesn't exist
}
I realize this only makes sense if you are using --pickererror mostly as a boolean (I thought since you're checking if its length is greater than 0). If you're actually using the string value, it would be better to create an --error-order variable for this single purpose I guess.
SASS CODE:
#{'body > *:not(.this)'} {
background: red;
}
EXPECTED RESULT
body > *:not(.this) {
background: red;
}
ACTUAL RESULT
body > * :not(.this) { //<-- SASS adds a space between * and :
background:red;
}
No matter what I try, SASS keeps adding an unnecessary space. How can I avoid this from happening? The space blocks the functionality of the not-selector.
This was not due to SASS. I was using CodeKit 3 and the following SASS setting messed it up:
Output style: Compressed
Put this on any other output style and you can avoid the above.
First of all, I am using LESS 1.7 (and there is no way I can change it). I have the following if-mixin in my less file that is just supposed to set the property and its value if the condition is met:
.if(#condition, #property, #value) when (#condition){
#{property}: #value !important;
}
It works fine if I pass the condition as true/false like this:
.column-header {
font-family: 'Something';
.if(true, color, green);
}
However, I am not able to pass the condition as an expression. If I want to pass a comparison such as 2 > 1, I get a parsing error: expected ')' got '>'. Is this not supported (or was this not supported in 1.7)? Am I doing something wrong? Any workaround? Thanks!
Not shure it's possible to pass contions to mixin.
But you can just write code witout .if mixin:
.column-header {
font-family: 'Something';
& when (2 > 1) {
color: green;
font-size: 20px;
}
}
I have a web form where some input fields are required and some are optional. I can give style the required fields as I expect but can't the optional ones.
When the optional fields have a valid input it will turn green(for instance). And it works with this code
input:optional:valid{
background: #AAB69B
}
But generally like as first loading they will be in another color. For this, I am trying this code
input:optional{
background: #f19999
}
But this doesn't work. I can't select the optional fields when they have no input. Unfortunately, with no input value they get the background as I set for the valid input. When I start typing , it get my expected invalid background. And when the input gets valid, the field gets valid background (it works).
Please, help !
Demo Link : http://bdlance.byethost9.com/front-end%20form%20validation%20with%20html5/
Taking a look at your form styles, I've seen that your background color is similar for both valid and invalid pseudo classes:
input:required:invalid, textarea:required:invalid{
background: #AAB69B; // same
}
input:required:focus:invalid, textarea:focus:invalid{
background: #AAB69B; // same
}
input:required:valid, textarea:required:valid{
background: #AAB69B; // same
}
input:optional, select {
background: #f19999;
}
input:optional:valid{
background: #AAB69B; // same
}
Try this instead:
input:required:invalid, textarea:required:invalid{
background: #f19999;
}
input:required:focus:invalid, textarea:focus:invalid{
background: #f19999;
}
input:required:valid, textarea:required:valid{
background: #AAB69B;
}
input:optional, select {
background: #f19999;
}
input:optional:valid{
background: #AAB69B;
}
Sorry, but your CSS file is not the best, Please do dedicate more time to learn CSS. Here are some good resources (the order matters):
https://developer.mozilla.org/en-US/docs/Learn/CSS
https://flukeout.github.io/
https://smacss.com/
https://en.bem.info/methodology/css/
On the site I'm working on we were using Scaffold, which is a PHP-based system similar to Sass. It also can process Sass functions\files. Unfortunately that system is now abandonware, and we are looking on a way to move completely to Sass. There is one big feature with Scaffold though that I'm not finding a way to port to Sass, the variable groups.
Variable in Scaffold can be organized in groups and used with a point-separated markup. For example I would define them as:
#variables vargroup1{
variable1: ####;
variable2: ####;
variable3: ####;
variable4: ####;
}
And later use on the code as, for example.
body{ width: vargroup1.variable1; margin: vargroup1.variable2 + 10;}
This helps development a lot, since you can group together variables from a system and reading the CSS files you can easily know what to reference. I didn't find anything like that on the Sass documentation, anyone knows if it is possible? Or if there is anyway using Mixins to do this?
Thanks
I came across this somewhat clunky solution (see Chris Eppstein's reply) using zip and index. Apparently a maintainer of SASS added these built-in functions in response to a similar question.
To quote his reply:
$border-names: a, b, c;
$border-widths: 1px, 1px, 2px;
$border-styles: solid, dashed, solid;
$border-colors: red, green, blue;
$borders: zip($border-widths, $border-styles, $border-colors);
#function border-for($name) {
#return nth($borders, index($border-names, $name))
}
#each $name in $border-names {
.border-#{$name} {
border: border-for($name);
}
}
Would generate:
.border-a { border: 1px solid red; }
.border-b { border: 1px dashed green; }
.border-c { border: 2px solid blue; }
The "naming your variables" comes from the list "-names" at the top; you then use the index of a desired variable name from that variable list to get the nth value from another variable lists. zip is used to mush separate lists together, so that you can retrieve the same index from all lists at the same time. Wrapping that behavior in a function makes it easier to retrieve a set.
There is no equivalent in Sass. But I can think in two workarounds:
1) Sass lists and its related list functions.
Your code could look like the following:
$variables = 40px 30px 20px 10px;
body {width: nth($variables, 1); margin: nth($variables, 2) + 10;}
It's not the same because list indexes can't be strings, so you haven't any way to name your variables.
2) Define a custom function. Look at Function Directives section in Sass reference
#function variables($variable_name) {
#if ($variable_name == 'variable1') {
#return 40px;
} #else if ($variable_name == 'variable2') {
#return 30px;
}
}
body {width: variables('variable_1'); margin: variables('variable_2') + 10;}
This way is less intuitive and uglier but you can 'name your variables'.
You could use the scss/sass map function:
#use "sass:map";
$variables: (
"variable1": ####;
"variable2": ####;
"variable3": ####;
"variable4": ####;
}
body {
width: map.get($variables, "variable1");
margin: map.get($variables, "variable2") + 10;
}
Documentation
You can use SASS lists a it's related functions on a way similar to that:
// List order: top, bottom, left, right, width, height, ...
$Header: 10px,auto,10px,auto,100%,50px;
$Footer: auto,0px,0px,auto,100%,20px;
#function getVar($variable,$name:top){
$var_index:1;
#if $name==bottom {
$var_index:2;
} #else if $name==left {
$var_index:3;
}
// Continue de if else for each property you want.
return nth($variable,$var_index);
}
That way calling something like:
getVar($Header,left)
Should return the value of the left property for the list of Header, but changing it to getVar($Footer,top) would return the value for the top property of the "Footer Group" (Footer List of Values).
That works for the time of using the values, but a the definition, you must follow the exact order and cannot leave any empty value, the nearest to an empty value that I found is #{''} what means "Empty String with no quotes", an empty value, but is added to the CSS.