This question already has answers here:
Unable to overwrite CSS variable with its own value
(2 answers)
CSS Variables - Swapping values?
(1 answer)
Can a recursive variable be expressed in css?
(2 answers)
Closed 2 years ago.
In CSS, can we we multiply a variable by some integer like the code below ?
:root {
--x: 1em;
}
.class2 {
--x: calc(2em * var(--x));
}
A quick check on the MDN docs unfortunately did not shine light on this. So unless you're willing to dive into the spec, here's a quick test:
:root {
--x: 4em;
}
.class2 {
--x: calc(0.5 * var(--x));
font-size: var(--x);
}
<div class="class2">
Test - doesn't work as intended
</div>
By the looks of it not only does the calculcation not work - which is unfortunate by itself - but it even seems to invalidate the custom property for .class2.
Just to make sure the formula/approach of using other variables to create computed variables in general is valid:
:root {
--x: 4em;
}
.class2 {
--y: calc(0.5 * var(--x));
font-size: var(--y);
}
<div class="class2">
Test - <strike>doesn't</strike> works as intended
</div>
This question already has answers here:
Can a CSS class inherit one or more other classes?
(29 answers)
Closed 7 years ago.
I would like to make one of my CSS property proportional to another, but none is parent of the other one. It would looks like this:
elem-to-look {
/**
* This value could not be explicit,
* And I want it to working even with default values.
*/
width: 50px;
}
elem-derivative {
/* I'm looking for something like this */
left: [elem-to-look: width] + 25px;
}
Is it even possible ? If no, what kind of solution would you advise me ?
Well, it is hard, but under some conditions you can do that.
If your body font-size is stable and you don't change it in parents of your elements, you can do the following:
body {
font-size: 20px;
}
elem-to-look {
width: 2.5em;
}
elem-derivative {
left: calc(2.5em + 25px);
}
If this satisfies you, that could work.
This question already has answers here:
Import regular CSS file in SCSS file?
(15 answers)
Closed 6 years ago.
I'm new to sass and I'm trying to import a parent theme's css in a Magento application.
I have it working to an extent but not with the result I was expecting.
In my styles.scss folder I have:
#import "../../../rwd/default/css/styles.css";
I have run the sass --watch styles.scss:styles.css in the terminal and the resulting styles.css file has:
#import url(../../../rwd/default/css/styles.css);
In the sass guide it says:
CSS has an import option that lets you split your CSS into smaller,
more maintainable portions. The only drawback is that each time you
use #import in CSS it creates another HTTP request. Sass builds on top
of the current CSS #import but instead of requiring an HTTP request,
Sass will take the file that you want to import and combine it with
the file you're importing into so you can serve a single CSS file to
the web browser.
So I was expecting SASS to import the css as plain old css rules rather than using the #import rule, so my styles.css would look something like:
/* ==========================================================================
HTML5 display definitions
========================================================================== */
/*
* Corrects `block` display not defined in IE 8/9.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section,
summary {
display: block;
}
/*
* Corrects `inline-block` display not defined in IE 8/9.
*/
audio,
canvas,
video {
display: inline-block;
}
/*
* Prevents modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/*
* Addresses styling for `hidden` attribute not present in IE 8/9.
*/
[hidden] {
display: none;
}
/* ==========================================================================
Base
========================================================================== */
/*
* 1. Sets default font family to sans-serif.
* 2. Prevents iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-family: sans-serif;
/* 1 */
-webkit-text-size-adjust: 100%;
/* 2 */
-ms-text-size-adjust: 100%;
/* 2 */
}
/*
* Removes default margin.
*/
body {
margin: 0;
}
/* ==========================================================================
Links
========================================================================== */
/*
* Addresses `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: thin dotted;
}
/*
* Improves readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/* ==========================================================================
Typography
========================================================================== */
/*
* Addresses `h1` font sizes within `section` and `article` in Firefox 4+,
* Safari 5, and Chrome.
*/
h1 {
font-size: 2em;
}
/*
* Addresses styling not present in IE 8/9, Safari 5, and Chrome.
*/
abbr[title] {
border-bottom: 1px dotted;
}
/*
* Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
*/
b,
strong {
font-weight: bold;
}
/*
* Addresses styling not present in Safari 5 and Chrome.
*/
dfn {
font-style: italic;
}
/*
* Addresses styling not present in IE 8/9.
*/
mark {
background: #ff0;
color: #000;
}
/*
* Corrects font family set oddly in Safari 5 and Chrome.
*/
code,
kbd,
pre,
samp {
font-family: monospace, serif;
font-size: 1em;
}
/*
* Improves readability of pre-formatted text in all browsers.
*/
pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
}
/*
* Sets consistent quote types.
*/
q {
quotes: "\201C" "\201D" "\2018" "\2019";
}
/*
* Addresses inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/*
* Prevents `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
That way I would have a styles.css on production which didn't use the #import rule.
I got it to work by following this article:
http://sass-lang.com/documentation/file.SASS_REFERENCE.html#import
#import by default looks for a Sass file to import directly, but if the is a .css file or if the filename is a url it will compile to a CSS #import rule. Both of which were the case for me.
So my solution was to copy the css file I wanted to import & rename it rwd_styles.scss & changed my scss import rule to #import "rwd_styles.scss"; and it worked as I had hoped.
I would like to use conditions in my CSS.
The idea is that I have a variable that I replace when the site is run to generate the right style-sheet.
I want it so that according to this variable the style-sheet changes!
It looks like:
[if {var} eq 2 ]
background-position : 150px 8px;
[else]
background-position : 4px 8px;
Can this be done? How do you do this?
Not in the traditional sense, but you can use classes for this, if you have access to the HTML. Consider this:
<p class="normal">Text</p>
<p class="active">Text</p>
and in your CSS file:
p.normal {
background-position : 150px 8px;
}
p.active {
background-position : 4px 8px;
}
That's the CSS way to do it.
Then there are CSS preprocessors like Sass. You can use conditionals there, which'd look like this:
$type: monster;
p {
#if $type == ocean {
color: blue;
} #else if $type == matador {
color: red;
} #else if $type == monster {
color: green;
} #else {
color: black;
}
}
Disadvantages are, that you're bound to pre-process your stylesheets, and that the condition is evaluated at compile time, not run time.
A newer feature of CSS proper are custom properties (a.k.a. CSS variables). They are evaluated at run time (in browsers supporting them).
With them you could do something along the line:
:root {
--main-bg-color: brown;
}
.one {
background-color: var(--main-bg-color);
}
.two {
background-color: black;
}
Finally, you can preprocess your stylesheet with your favourite server-side language. If you're using PHP, serve a style.css.php file, that looks something like this:
p {
background-position: <?php echo (#$_GET['foo'] == 'bar')? "150" : "4"; ?>px 8px;
}
In this case, you will however have a performance impact, since caching such a stylesheet will be difficult.
I am surprised that nobody has mentioned CSS pseudo-classes, which are also a sort-of conditionals in CSS. You can do some pretty advanced things with this, without a single line of JavaScript.
Some pseudo-classes:
:active - Is the element being clicked?
:checked - Is the radio/checkbox/option checked? (This allows for conditional styling through the use of a checkbox!)
:empty - Is the element empty?
:fullscreen - Is the document in full-screen mode?
:focus - Does the element have keyboard focus?
:focus-within - Does the element, or any of its children, have keyboard focus?
:has([selector]) - Does the element contain a child that matches [selector]? (Sadly, not supported by any of the major browsers.)
:hover - Does the mouse hover over this element?
:in-range/:out-of-range - Is the input value between/outside min and max limits?
:invalid/:valid - Does the form element have invalid/valid contents?
:link - Is this an unvisited link?
:not() - Invert the selector.
:target - Is this element the target of the URL fragment?
:visited - Has the user visited this link before?
Example:
div { color: white; background: red }
input:checked + div { background: green }
<input type=checkbox>Click me!
<div>Red or green?</div>
Update:
I've written a article regarding the below unique method in CSS-Tricks which goes into futher detail
I've devised the below demo using a mix of tricks which allows simulating if/else scenarios for some properties. Any property which is numerical in its essence is easy target for this method, but properties with text values are.
This code has 3 if/else scenarios, for opacity, background color & width. All 3 are governed by two Boolean variables bool and its opposite notBool.
Those two Booleans are the key to this method, and to achieve a Boolean out of a none-boolean dynamic value, requires some math which luckily CSS allows using min & max functions.
Obviously those functions (min/max) are supported in recent browsers' versions which also supports CSS custom properties (variables).
var elm = document.querySelector('div')
setInterval(()=>{
elm.style.setProperty('--width', Math.round(Math.random()*80 + 20))
}, 1000)
:root{
--color1: lightgreen;
--color2: salmon;
--width: 70; /* starting value, randomly changed by javascript every 1 second */
}
div{
--widthThreshold: 50;
--is-width-above-limit: Min(1, Max(var(--width) - var(--widthThreshold), 0));
--is-width-below-limit: calc(1 - var(--is-width-above-limit));
--opacity-wide: .4; /* if width is ABOVE 50 */
--radius-narrow: 10px; /* if width is BELOW 50 */
--radius-wide: 60px; /* if width is ABOVE 50 */
--height-narrow: 80px; /* if width is ABOVE 50 */
--height-wide: 160px; /* if width is ABOVE 50 */
--radiusToggle: Max(var(--radius-narrow), var(--radius-wide) * var(--is-width-above-limit));
--opacityToggle: calc(calc(1 + var(--opacity-wide)) - var(--is-width-above-limit));
--colorsToggle: var(--color1) calc(100% * var(--is-width-above-limit)),
var(--color2) calc(100% * var(--is-width-above-limit)),
var(--color2) calc(100% * (1 - var(--is-width-above-limit)));
--height: Max(var(--height-wide) * var(--is-width-above-limit), var(--height-narrow));
height: var(--height);
text-align: center;
line-height: var(--height);
width: calc(var(--width) * 1%);
opacity: var(--opacityToggle);
border-radius: var(--radiusToggle);
background: linear-gradient(var(--colorsToggle));
transition: .3s;
}
/* prints some variables */
div::before{
counter-reset: aa var(--width);
content: counter(aa)"%";
}
div::after{
counter-reset: bb var(--is-width-above-limit);
content: " is over 50% ? "counter(bb);
}
<div></div>
Another simple way using clamp:
label{ --width: 150 }
input:checked + div{ --width: 400 }
div{
--isWide: Clamp(0, (var(--width) - 150) * 99999, 1);
width: calc(var(--width) * 1px);
height: 150px;
border-radius: calc(var(--isWide) * 20px); /* if wide - add radius */
background: lightgreen;
}
<label>
<input type='checkbox' hidden>
<div>Click to toggle width</div>
</label>
Best so far:
I have come up with a totally unique method, which is even simpler!
This method is so cool because it is so easy to implement and also to understand. it is based on animation step() function.
Since bool can be easily calculated as either 0 or 1, this value can be used in the step! if only a single step is defined, then the if/else problem is solved.
Using the keyword forwards persist the changes.
var elm = document.querySelector('div')
setInterval(()=>{
elm.style.setProperty('--width', Math.round(Math.random()*80 + 20))
}, 1000)
:root{
--color1: salmon;
--color2: lightgreen;
}
#keyframes if-over-threshold--container{
to{
--height: 160px;
--radius: 30px;
--color: var(--color2);
opacity: .4; /* consider this as additional, never-before, style */
}
}
#keyframes if-over-threshold--after{
to{
content: "true";
color: green;
}
}
div{
--width: 70; /* must be unitless */
--height: 80px;
--radius: 10px;
--color: var(--color1);
--widthThreshold: 50;
--is-width-over-threshold: Min(1, Max(var(--width) - var(--widthThreshold), 0));
text-align: center;
white-space: nowrap;
transition: .3s;
/* if element is narrower than --widthThreshold */
width: calc(var(--width) * 1%);
height: var(--height);
line-height: var(--height);
border-radius: var(--radius);
background: var(--color);
/* else */
animation: if-over-threshold--container forwards steps(var(--is-width-over-threshold));
}
/* prints some variables */
div::before{
counter-reset: aa var(--width);
content: counter(aa)"% is over 50% width ? ";
}
div::after{
content: 'false';
font-weight: bold;
color: darkred;
/* if element is wider than --widthThreshold */
animation: if-over-threshold--after forwards steps(var(--is-width-over-threshold)) ;
}
<div></div>
I've found a Chrome bug which I have reported that can affect this method in some situations where specific type of calculations is necessary, but there's a way around it.
You can use calc() in combination with var() to sort of mimic conditionals:
:root {
--var-eq-two: 0;
}
.var-eq-two {
--var-eq-two: 1;
}
.block {
background-position: calc(
150px * var(--var-eq-two) +
4px * (1 - var(--var-eq-two))
) 8px;
}
concept
Below is my old answer which is still valid but I have a more opinionated approach today:
One of the reasons why CSS sucks so much is exactly that it doesn't have conditional syntax. CSS is per se completely unusable in the modern web stack. Use SASS for just a little while and you'll know why I say that. SASS has conditional syntax... and a LOT of other advantages over primitive CSS too.
Old answer (still valid):
It cannot be done in CSS in general!
You have the browser conditionals like:
/*[if IE]*/
body {height:100%;}
/*[endif]*/
But nobody keeps you from using Javascript to alter the DOM or assigning classes dynamically or even concatenating styles in your respective programming language.
I sometimes send css classes as strings to the view and echo them into the code like that (php):
<div id="myid" class="<?php echo $this->cssClass; ?>">content</div>
You could create two separate stylesheets and include one of them based on the comparison result
In one of the you can put
background-position : 150px 8px;
In the other one
background-position : 4px 8px;
I think that the only check you can perform in CSS is browser recognition:
Conditional-CSS
CSS is a nicely designed paradigm, and many of it's features are not much used.
If by a condition and variable you mean a mechanism to distribute a change of some value to the whole document, or under a scope of some element, then this is how to do it:
var myVar = 4;
document.body.className = (myVar == 5 ? "active" : "normal");
body.active .menuItem {
background-position : 150px 8px;
background-color: black;
}
body.normal .menuItem {
background-position : 4px 8px;
background-color: green;
}
<body>
<div class="menuItem"></div>
</body>
This way, you distribute the impact of the variable throughout the CSS styles.
This is similar to what #amichai and #SeReGa propose, but more versatile.
Another such trick is to distribute the ID of some active item throughout the document, e.g. again when highlighting a menu: (Freemarker syntax used)
var chosenCategory = 15;
document.body.className = "category" + chosenCategory;
<#list categories as cat >
body.category${cat.id} .menuItem { font-weight: bold; }
</#list>
<body>
<div class="menuItem"></div>
</body>
Sure,this is only practical with a limited set of items, like categories or states, and not unlimited sets like e-shop goods, otherwise the generated CSS would be too big. But it is especially convenient when generating static offline documents.
One more trick to do "conditions" with CSS in combination with the generating platform is this:
.myList {
/* Default list formatting */
}
.myList.count0 {
/* Hide the list when there is no item. */
display: none;
}
.myList.count1 {
/* Special treatment if there is just 1 item */
color: gray;
}
<ul class="myList count${items.size()}">
<!-- Iterate list's items here -->
<li>Something...</div>
</ul>
You can use not instead of if like
.Container *:not(a)
{
color: #fff;
}
Set the server up to parse css files as PHP and then define the variable variable with a simple PHP statement.
Of course this assumes you are using PHP...
This is a little extra info to the Boldewyn answer above.
Add some php code to do the if/else
if($x==1){
print "<p class=\"normal\">Text</p>\n";
} else {
print "<p class=\"active\">Text</p>\n";
}
CSS has a feature: Conditional Rules. This feature of CSS is applied based on a specific condition. Conditional Rules are:
#supports
#media
#document
Syntax:
#supports ("condition") {
/* your css style */
}
Example code snippet:
<!DOCTYPE html>
<html>
<head>
<title>Supports Rule</title>
<style>
#supports (display: block) {
section h1 {
background-color: pink;
color: white;
}
section h2 {
background-color: pink;
color: black;
}
}
</style>
</head>
<body>
<section>
<h1>Stackoverflow</h1>
<h2>Stackoverflow</h2>
</section>
</body>
</html>
As far as i know, there is no if/then/else in css. Alternatively, you can use javascript function to alter the background-position property of an element.
Yet another option (based on whether you want that if statement to be dynamically evaluated or not) is to use the C preprocessor, as described here.
You can use javascript for this purpose, this way:
first you set the CSS for the 'normal' class and for the 'active' class
then you give to your element the id 'MyElement'
and now you make your condition in JavaScript, something like the example below... (you can run it, change the value of myVar to 5 and you will see how it works)
var myVar = 4;
if(myVar == 5){
document.getElementById("MyElement").className = "active";
}
else{
document.getElementById("MyElement").className = "normal";
}
.active{
background-position : 150px 8px;
background-color: black;
}
.normal{
background-position : 4px 8px;
background-color: green;
}
div{
width: 100px;
height: 100px;
}
<div id="MyElement">
</div>
You can add container div for all your condition scope.
Add the condition value as a class to the container div. (you can set it by server side programming - php/asp...)
<!--container div-->
<div class="true-value">
<!-- your content -->
<p>my content</p>
<p>my content</p>
<p>my content</p>
</div>
Now you can use the container class as a global variable for all elements in the div using a nested selector, without adding the class to each element.
.true-value p{
background-color:green;
}
.false-value p{
background-color:red;
}
Besides the answers above, soon another way to directly use if/else -like conditions, and even more closely aligned with other scripting languages, would be via #when / #else conditionals. These conditionals would be implemented to exercise easily recognizable logic chain, for example:
#when supports(display: flex) {
.container {
display: flex
}
} #else media and (min-width: 768px) {
.container {
min-width: 768px
}
} #else {
.container {
width: 100%
}
}
As of February 2022 there is no browser support. Please see this W3C module for more info.
(Yes, old thread. But it turned up on top of a Google-search so others might be interested as well)
I guess the if/else-logic could be done with javascript, which in turn can dynamically load/unload stylesheets. I haven't tested this across browsers etc. but it should work. This will get you started:
http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
If you're open to using jquery, you can set conditional statements using javascript within the html:
$('.class').css("color",((Variable > 0) ? "#009933":"#000"));
This will change the text color of .class to green if the value of Variable is greater than 0.
Leaving aside the question of whether you should serve single or multiple stylesheets, assuming you're sending just one, what do you think of this as a basic structure?
/* Structure */
Any template layout stuff should be put into here, so header, footer, body etc.
/* Structure End */
/* Common Components*/
Repeated elements, such as signup forms, lists, etc.
/* Common Components End*/
/* Specific Page 1 */
Some pages might have specific styles, that would go here.
/* Specific Page 1 End */
/* Specific Page 2 */
As above
/* Specific Page 2 End */
/* Specific Page etc */
And so on.
/* Specific Page etc End */
That's similar to how I structure mine, however, I find that using sub-headings is the best way to do it, so I use this structure:
/*************************
* GLOBAL *
*************************/
/* All of the common stuff goes here under the appropriate sub headings */
/* Heading formatting */
/* Text formatting */
/* Form formatting */
/* Table formatting */
/* etc */
/*************************
* LAYOUT *
*************************/
/* All the layout things go here under sub-headings */
/* Header */
/* Left Sidebar */
/* Right Sidebar */
/* Footer */
/*************************
* NAVIGATION *
*************************/
/* I put navigation separate to the layout as there can be a number of navigation points under their sub-headings */
/* Main (horizontal) Navigation */
/* Left Navigation */
/* Right Navigation */
/* Breadcrumb Navigation */
/*************************
* FORMS *
*************************/
/* Any form formatting that varies from the common formatting, if there are multiple differently formatted forms, then use sub-headings */
/*************************
* TABLES *
*************************/
/* Same deal as forms */
/*************************
* LISTS *
*************************/
/* Same deal as forms and tables */
/*************************
* CONTENT *
*************************/
/* Any specific formatting for particular pages, grouped by sub-headings for the page the same way as forms, tables and lists */
/*************************
* CSS SUPPORT *
*************************/
/* This is for any special formatting that can be applied to any element on any page and have it override the regular formatting for that item. For example, this might have things like: */
.float-right { float: right; }
.float-left { float: left; }
.float-center { margin-left: auto; margin-right: auto; }
.clear { clear: both }
.clear-block { display: block }
.text-left { text-align: left }
.text-right { text-align: right }
.text-center { text-align: center }
.text-justify { text-align: justify }
.bold { font-weight: bold }
.italic { font-style: italic }
.underline { border-bottom: 1px solid }
.nopadding { padding: 0 }
.nobullet { list-style: none; list-style-image: none }
/* etc */
Hope that helps.
I generally don't recommend writing on a single line like that though, or like suggested in the link Adam posted, they get very difficult to skim over if they get long. For the examples above, it was just quicker to type them that way so I didn't have to indent every line.
For formatting I would recommend this structure:
.class {
width: 200px;
height: 200px;
border: 1px solid #000000;
}
And so on, I put the structure of the class or ID at the top, then any other formatting, like the font etc below that. Makes it very quick and clear to skim over.
Whatever makes sense to you is good enough. Frankly, when someone else comes looking for something in your stylesheet - or when you come looking for something, for that matter - they're not going to try to figure out what your organizing structure was. They're just going to search for whatever class or element they need to see. So as long as you generally keep stuff that's related together, and section things off with comments like #Matt suggests, you're fine.
The fact of the matter is that even with a very well-thought-out organizational structure - just like with a well-thought-out filing system - it's not always obvious what goes where; so you're better off just being somewhat sensible, not devoting a lot of time to keeping things organized, and relying on search tools to find what you need.
I organize my CSS in a similar way as yours but I do start with a reset section. The main idea is to go from general to specific. So here it goes:
reset
structure
html_tags
navigation
specific sections
Error messages - that's my last section
The structure you presented is exactly what I use. However, it seems to me that it still got too complex with new rules showing up and overriding each other... Perhaps I should try to stick to the solution suggested in the topic linked to by Adam instead.
It seems like every time I create a new css file, I find a new way to organize it. And they are ALL better than the previous.