What exactly does !default do in CSS? [duplicate] - css

The twitter bootstrap code has a lot of CSS properties with a !default at the end.
E.g.
p {
color: white !default;
}
What does !default do?
UPDATE
My bad for not being clear. I am using the SASS part of Bootstrap.

!default is used often in Bootstrap Sass. It is similar to a reverse !important. All of Bootstraps Variables are set using !default to allow the developer to further customize bootstrap. With !default sass will only define a variable if it has not already been set.
This allows for more flexibility.
//Example1 Dress color = red
$auroras-dress-color: blue;
$auroras-dress-color: red;
//Example2 Dress color = red
$auroras-dress-color: blue !default;
$auroras-dress-color: red;
//Example3 Dress color = blue
$auroras-dress-color: blue;
$auroras-dress-color: red !default;
So Why is this important?
Bootstrap is a package. Most people don't edit the Bootstrap source. NEVER UPDATE THE BOOTSTRAP SOURCE. To customize bootstrap you will add your own variable file and compile it with the bootstrap code but never touch the native bootstrap package. Bootstrap sass's page has the full skinny on how to customize and compile it in the documentations.
I don't know why less does not do this. I have not worked much with less and do not know if it has it's own built in variable management.
Example fiddle
https://jsfiddle.net/siggysid/344dnnwz/

Twitter Bootstrap uses LESS as far as I've seen. On the other hand, !default is actually part of Sass, and is used for giving Sass variables ($var) default values, which would make it invalid in your given context, even in Sass.
Besides, I've not been able to find any references to !default in the LESS documentation, and to my knowledge it is exclusive to Sass. Are you sure you found this in Bootstrap's source and not elsewhere? Because I honestly don't remember seeing Sass/SCSS code in Bootstrap's stylesheets.
For what it's worth, the only valid token that starts with ! in CSS is !important, which you may already be aware of.

You can find the following exact definition and a decent explanation in sass-lang website in its doc section (variable) - default value:
Normally when you assign a value to a variable, if that variable already had a value, its old value is overwritten. But if you’re writing a Sass library, you might want to allow your users to configure your library’s variables before you use them to generate CSS.
To make this possible, Sass provides the !default flag. This assigns a value to a variable only if that variable isn’t defined or its value is null. Otherwise, the existing value will be used.

default-values
if that variable isn’t defined or its value is null. Otherwise, the existing value will be used.
Example
case 1: null
// test.sass
$MySize: null
$MySize: 5rem!default // since MySize is "null" so use default
h1
font-size: $MySize
output CSS
h1 {
font-size: 5rem;
}
case 2: undefined
// test.sass
$MySize: 5rem!default // since MySize is "undefined" so use default
h1
font-size: $MySize
output CSS
h1 {
font-size: 5rem;
}
case 3: defined already
// test.sass
$MySize: 30rem
$MySize: 5rem!default // since MySize has been defined. So ignore this setting.
h1
font-size: $MySize
output CSS
h1 {
font-size: 30rem;
}

Here is an example.
$white: white !default;
If you don't define the $white before the code block above, then the $white will be white.
If you define it like this
$white: #eee;
then the $white will be #eee
Here is a link about it in bootstrap-vue,

Related

Use CSS variables and Sass mixing together without Sass vars

I want to user var(--darkGrey). So far I have tried this:
$grey: #ddd; // I'd like to remove this line
:root {
--grey: #ddd;
--darkGrey: darken($grey, 55%); // doesn't fail but doesn't work
--darkGrey: darken(#ddd, 55%); // doesn't fail but doesn't work
--darkGrey1: #{darken($grey, 55%)}; // works but I don't like having a Sass var
--darkGrey2: #{darken(var(--grey), 55%)}; // fails: "var(--grey)" is not a color for `darken'
--darkGrey3: #{darken(#ddd, 55%)}; // works but I'd need to use a css var. I have plenty of colors and references
}
I'd say it does not make much sense to use CSS custom property (variable) in Sass function. CSS custom properties could be changed deeper in your CSS structure or even during the runtime, while Sass is available only during compile time. It could not react to such change.
Have a look at hsla() CSS function, which can be used to change lightness of colors during runtime. See article https://sparanoid.com/note/css-variables-guide/.

Custom css properties in lighten/darken scss function

as the question suggested, I want to use custom css colors (with --color*) inside a lighten/darken function. The reason is that I have an Ionic application and I want to change the theme colors dynamically, something like this:
--ion-color-primary: #fff;
--ion-color-primary-rgb: 255, 255, 255;
--ion-color-primary-contrast: #000);
--ion-color-primary-contrast-rgb: 0, 0, 0;
--ion-color-primary-shade: darken(var(--ion-color-primary, 30);
--ion-color-primary-tint: lighten(var(--ion-color-primary, 30);
I am receiving the primary and primary-contrast css properties from other place and I want to be able to set the shade and tint dynamically based on them. With the code above, I received an error saying $color: var(--ion-color-primary) is not a color.
Code snipper
There is a breaking change in Sass since v3.5.0 where you need to write your sass variables and functions within interpolation.
To provide maximum compatibility with plain CSS, more recent versions of Sass require SassScript expressions in custom property values to be written within interpolation. Interpolation will also work for older Sass versions, and so is recommended for all stylesheets.*
Therefore your code should look like this:
$primary: aqua;
--ion-color-primary-shade: #{darken($primary, 30%)};
--ion-color-primary-tint: #{lighten($primary, 30%)};
For the best effect to achieve consider using scale-color() instead of darken/lighten:
The lighten() function increases lightness by a fixed amount, which is often not the desired effect. To make a color a certain percentage lighter than it was before, use scale() instead.**
$primary: aqua;
--ion-color-primary-shade: #{scale-color($primary, $lightness: -30%)};
--ion-color-primary-tint: #{scale-color($primary, $lightness: 30%)};
*For more info about sass interpolation see https://sass-lang.com/documentation/breaking-changes/css-vars.
**For more details on scale-color: https://sass-lang.com/documentation/modules/color#scale

How to modify a parameter's value in sass files from typescript?

I am trying to change a variable's value in "../myStyle.scss" file from myComponent.ts . I read that it is impossible to achieve it because sass file are compiled into css by the sass pre-processor and the variable disapears. Isn't there a way to work this around.
My variable is called $theme.
And I want to change it's value.
$theme: #5A352A;
and I want it to become $theme: #ffffff; when the user clicks
You have to work in a different way.
Basically when you compile the angular app , it will generate a css file where it substitute the variable with the value , wherever you used it.
So if you want to achieve a color change you have to create a other variable and other classes and swipe it in your class attributes (this is one way, check also ngStyle and ngClass in angular reference).
For example white-theme/dark-theme (the most common case).
variables -> $black: #00000; $white: #ffffff
Example classes:
.body-dark {
background-color: $black;
}
.body-white {
background-color: $white;
}
and swipe the classes in the html elements.
setDark(){
document.getElementById("bodyId").setAttribute("class","body-dark ")
}
the same for white.

Bootstrap 4 custom variables don't cascade down?

So here's kind of a weird thing with the custom.scss file in bootstrap that I discovered tonight and wondering if I am missing something. Let's say I set the color $blue to a custom value (#000 in this case just to make it easy to read) and remove the !default flag in _custom.scss as I'm supposed to. In the _variables.scss file, the color $brand-primary is set to $blue, with a !default flag. Then, the $btn-primary-bg is set to $brand-primary, also with a !default flag. So, my thinking is if I set:
$blue: #000000;
in the custom.scss file, it should then cascade down to any variable using $blue, making it so that:
$brand-primary: $blue; set to #000 and then
$btn-primary-bg: $brand-primary; also set to #000000
Well, turns out I have to list all 3 of those instances in the custom sass file and remove their !default flag before they would change to the custom color.
So instead of my custom sheet just having one line
$blue: #000000;
it needs to be
$blue: #000000 ;
$brand-primary: $blue;
$btn-primary-bg: $brand-primary;
before that custom color gets applied to those classes.
Am I missing something here? Shouldn't we just have to set the custom color once and then any variable referencing it would also reference that custom color? Seems inefficient to me at this point.
[enter link description here][1]There is no problem with the variables have been defined. Probably you need to change the way you have used them in HTML. Have a look at below example which has been provided based on your defined variables. I would suggest remove "$blue" variable and define the color directly for "$brand-primary" variable!
[1]: https://jsfiddle.net/negin/t36ep4e8/

How can I define colors as variables in CSS?

I’m working on a CSS file that is quite long. I know that the client could ask for changes to the color scheme, and was wondering: is it possible to assign colors to variables, so that I can just change a variable to have the new color applied to all elements that use it?
Please note that I can’t use PHP to dynamically change the CSS file.
CSS supports this natively with CSS Variables.
Example CSS file
:root {
--main-color:#06c;
}
#foo {
color: var(--main-color);
}
For a working example, please see this JSFiddle (the example shows one of the CSS selectors in the fiddle has the color hard coded to blue, the other CSS selector uses CSS variables, both original and current syntax, to set the color to blue).
Manipulating a CSS variable in JavaScript/client side
document.body.style.setProperty('--main-color',"#6c0")
Support is in all the modern browsers
Firefox 31+, Chrome 49+, Safari 9.1+, Microsoft Edge 15+ and Opera 36+ ship with native support for CSS variables.
People keep upvoting my answer, but it's a terrible solution compared to the joy of sass or less, particularly given the number of easy to use gui's for both these days. If you have any sense ignore everything I suggest below.
You could put a comment in the css before each colour in order to serve as a sort of variable, which you can change the value of using find/replace, so...
At the top of the css file
/********************* Colour reference chart****************
*************************** comment ********* colour ********
box background colour bbg #567890
box border colour bb #abcdef
box text colour bt #123456
*/
Later in the CSS file
.contentBox {background: /*bbg*/#567890; border: 2px solid /*bb*/#abcdef; color:/*bt*/#123456}
Then to, for example, change the colour scheme for the box text you do a find/replace on
/*bt*/#123456
Yeeeaaahhh.... you can now use var() function in CSS.....
The good news is you can change it using JavaScript access, which will change globally as well...
But how to declare them...
It's quite simple:
For example, you wanna assign a #ff0000 to a var(), just simply assign it in :root, also pay attention to --:
:root {
--red: #ff0000;
}
html, body {
background-color: var(--red);
}
The good things are the browser support is not bad, also don't need to be compiled to be used in the browser like LESS or SASS...
Also, here is a simple JavaScript script, which changes the red value to blue:
const rootEl = document.querySelector(':root');
root.style.setProperty('--red', 'blue');
CSS itself doesn't use variables. However, you can use another language like SASS to define your styling using variables, and automatically produce CSS files, which you can then put up on the web. Note that you would have to re-run the generator every time you made a change to your CSS, but that isn't so hard.
You can try CSS3 variables:
body {
--fontColor: red;
color: var(--fontColor);
}
There's no easy CSS only solution. You could do this:
Find all instances of background-color and color in your CSS file and create a class name for each unique color.
.top-header { color: #fff; }
.content-text { color: #f00; }
.bg-leftnav { background-color: #fff; }
.bg-column { background-color: #f00; }
Next go through every single page on your site where color was involved and add the appropriate classes for both color and background color.
Last, remove any references of colors in your CSS other than your newly created color classes.
The 'Less' Ruby Gem for CSS looks awesome.
http://lesscss.org/
Yes, in near future (i write this in june 2012) you can define native css variables, without using less/sass etc ! The Webkit engine just implemented first css variable rules, so cutting edge versions of Chrome and Safari are already to work with them. See the Official Webkit (Chrome/Safari) development log with a onsite css browser demo.
Hopefully we can expect widespread browser support of native css variables in the next few months.
Do not use css3 variables due to support.
I would do the following if you want a pure css solution.
Use color classes with semenatic names.
.bg-primary { background: #880000; }
.bg-secondary { background: #008800; }
.bg-accent { background: #F5F5F5; }
Separate the structure from the skin (OOCSS)
/* Instead of */
h1 {
font-size: 2rem;
line-height: 1.5rem;
color: #8000;
}
/* use this */
h1 {
font-size: 2rem;
line-height: 1.5rem;
}
.bg-primary {
background: #880000;
}
/* This will allow you to reuse colors in your design */
Put these inside a separate css file to change as needed.
Sure can, sort of, thanks to the wonderful world of multiple classes, can do this:
.red {color:red}
.blackBack {background-color: black}
but I often end up combining them anyway like this:
.highlight {color:red, background-color: black}
I know the semantic police will be all over you, but it works.
I'm not clear on why you can't use PHP. You could then simply add and use variables as you wish, save the file as a PHP file and link to that .php file as the style sheet instead of the .css file.
It doesn't have to be PHP, but you get what I mean.
When we want programming stuff, why not use a programming language until CSS (maybe) supports things like variables?
Also, check out Nicole Sullivan's Object-oriented CSS.
You can group selectors:
#selector1, #selector2, #selector3 { color: black; }
You could pass the CSS through javascript and replace all instances of COLOUR1 with a certain color (basically regex it) and provide a backup stylesheet incase the end user has JS turned off
dicejs.com (formally cssobjs) is a client-side version of SASS. You can set variables in your CSS (stored in json formatted CSS) and re-use your color variables.
//create the CSS JSON object with variables and styles
var myCSSObjs = {
cssVariables : {
primaryColor:'#FF0000',
padSmall:'5px',
padLarge:'$expr($padSmall * 2)'
}
'body' : {padding:'$padLarge'},
'h1' : {margin:'0', padding:'0 0 $padSmall 0'},
'.pretty' : {padding:'$padSmall', margin:'$padSmall', color:'$primaryColor'}
};
//give your css objects a name and inject them
$.cssObjs('myStyles',myCSSObjs).injectStyles();
And here is a link to a complete downloadable demo which is a little more helpful then their documentation : dicejs demo
EDIT: This answer is no longer current. You should use CSS variables now.
Consider using SCSS. It's full compatible with CSS syntax, so a valid CSS file is also a valid SCSS file. This makes migration easy, just change the suffix. It has numerous enhancements, the most useful being variables and nested selectors.
You need to run it through a pre-processor to convert it to CSS before shipping it to the client.
I've been a hardcore CSS developer for many years now, but since forcing myself to do a project in SCSS, I now won't use anything else.
If you have Ruby on your system you can do this:
http://unixgods.org/~tilo/Ruby/Using_Variables_in_CSS_Files_with_Ruby_on_Rails.html
This was made for Rails, but see below for how to modify it to run it stand alone.
You could use this method independently from Rails, by writing a small Ruby wrapper script
which works in conjunction with site_settings.rb and takes your CSS-paths into account, and
which you can call every time you want to re-generate your CSS (e.g. during site startup)
You can run Ruby on pretty much any operating system, so this should be fairly platform independent.
e.g. wrapper: generate_CSS.rb (run this script whenever you need to generate your CSS)
#/usr/bin/ruby # preferably Ruby 1.9.2 or higher
require './site_settings.rb' # assuming your site_settings file is on the same level
CSS_IN_PATH = File.join( PATH-TO-YOUR-PROJECT, 'css-input-files')
CSS_OUT_PATH = File.join( PATH-TO-YOUR-PROJECT, 'static' , 'stylesheets' )
Site.generate_CSS_files( CSS_IN_PATH , CSS_OUT_PATH )
the generate_CSS_files method in site_settings.rb then needs to be modified like this:
module Site
# ... see above link for complete contents
# Module Method which generates an OUTPUT CSS file *.css for each INPUT CSS file *.css.in we find in our CSS directory
# replacing any mention of Color Constants , e.g. #SomeColor# , with the corresponding color code defined in Site::Color
#
# We will only generate CSS files if they are deleted or the input file is newer / modified
#
def self.generate_CSS_files(input_path = File.join( Rails.root.to_s , 'public' ,'stylesheets') ,
output_path = File.join( Rails.root.to_s , 'public' ,'stylesheets'))
# assuming all your CSS files live under "./public/stylesheets"
Dir.glob( File.join( input_path, '*.css.in') ).each do |filename_in|
filename_out = File.join( output_path , File.basename( filename_in.sub(/.in$/, '') ))
# if the output CSS file doesn't exist, or the the input CSS file is newer than the output CSS file:
if (! File.exists?(filename_out)) || (File.stat( filename_in ).mtime > File.stat( filename_out ).mtime)
# in this case, we'll need to create the output CSS file fresh:
puts " processing #{filename_in}\n --> generating #{filename_out}"
out_file = File.open( filename_out, 'w' )
File.open( filename_in , 'r' ).each do |line|
if line =~ /^\s*\/\*/ || line =~ /^\s+$/ # ignore empty lines, and lines starting with a comment
out_file.print(line)
next
end
while line =~ /#(\w+)#/ do # substitute all the constants in each line
line.sub!( /#\w+#/ , Site::Color.const_get( $1 ) ) # with the color the constant defines
end
out_file.print(line)
end
out_file.close
end # if ..
end
end # def self.generate_CSS_files
end # module Site
Not PHP I'm afraid, but Zope and Plone use something similar to SASS called DTML to achieve this. It's incredibly useful in CMS's.
Upfront Systems has a good example of its use in Plone.
If you write the css file as an xsl template, you could read color values from a simple xml file. Then create the css with an xslt processor.
colors.xml:
<?xml version="1.0"?>
<colors>
<background>#ccc</background>
</colors>
styles.xsl:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" version="1.0" encoding="iso-8859-1"/>
<xsl:template match="/">body {
background-color: <xsl:value-of select="/colors/background" />;
}
</xsl:template>
</xsl:stylesheet>
Command to render css: xsltproc -o styles.css styles.xsl colors.xml
styles.css:
body {
background-color: #ccc;
}
It’s not possible with CSS alone.
You can do it with JavaScript and LESS using less.js, which will render LESS variables into CSS live, but it’s for development only and adds too much overhead for real-life use.
The closest you can come with CSS is to use an attribute substring selector like this:
[id*="colvar-"] {
color: #f0c69b;
}
and set the ids of all your elements that you want to be adjusted to names starting with colvar-, such as colvar-header. Then when you change the color, all the ID styles are updated. That’s as close as you can get with CSS alone.

Resources