Is there any way to use conditional statements in CSS?
I'd say the closest thing to "IF" in CSS are media queries, such as those you can use for responsive design. With media queries, you're saying things like, "If the screen is between 440px and 660px wide, do this". Read more about media queries here: http://www.w3schools.com/cssref/css3_pr_mediaquery.asp, and here's an example of how they look:
#media screen and (max-width: 300px) {
body {
background-color: lightblue;
}
}
That's pretty much the extent of "IF" within CSS, except to move over to SASS/SCSS (as mentioned above).
I think your best bet is to change your classes / IDs within the scripting language, and then treat each of the class/ID options in your CSS. For instance, in PHP, it might be something like:
<?php
if( A > B ){
echo '<div class="option-a">';
}
else{
echo '<div class="option-b">';
}
?>
Then your CSS can be like
.option-a {
background-color:red;
}
.option-b {
background-color:blue;
}
No. But can you give an example what you have in mind? What condition do you want to check?
Maybe Sass or Compass are interesting for you.
Quote from Sass:
Sass makes CSS fun again. Sass is CSS, plus nested rules, variables, mixins, and more, all in a concise, readable syntax.
CSS itself doesn't have conditional statements, but here's a hack involving custom properties (a.k.a. "css variables").
In this trivial example, you want to apply a padding based on a certain condition—like an "if" statement.
:root { --is-big: 0; }
.is-big { --is-big: 1; }
.block {
padding: calc(
4rem * var(--is-big) +
1rem * (1 - var(--is-big))
);
}
So any .block that's an .is-big or that's a descendant of one will have a padding of 4rem, while all other blocks will only have 1rem. Now I call this a "trivial" example because it can be done without the hack.
.block {
padding: 1rem;
}
.is-big .block,
.block.is-big {
padding: 4rem;
}
But I will leave its applications to your imagination.
The #supports rule (92% browser support July 2017) rule can be used for conditional logic on css properties:
#supports (display: -webkit-box) {
.for_older_webkit_browser { display: -webkit-box }
}
#supports not (display: -webkit-box) {
.newer_browsers { display: flex }
}
The only conditions available in CSS are selectors and #media. Some browsers support some of the CSS 3 selectors and media queries.
You can modify an element with JavaScript to change if it matches a selector or not (e.g. by adding a new class).
I would argue that you can use if statements in CSS. Although they aren't worded as such. In the example below, I've said that if the check-box is checked I want the background changed to white. If you want to see a working example check out www.armstrongdes.com. I built this for a client. Re size your window so that the mobile navigation takes over and click the nav button. All CSS. I think it's safe to say this concept could be used for many things.
#sidebartoggler:checked + .page-wrap .hamb {
background: #fff;
}
// example set as if statement sudo code.
if (sidebaretoggler is checked == true) {
set the background color of .hamb to white;
}
CSS has become a very powerful tool over the years and it has hacks for a lot of things javaScript can do
There is a hack in CSS for using conditional statements/logic.
It involves using the symbol '~'
Let me further illustrate with an example.
Let's say you want a background to slide into the page when a button is clicked. All you need to do is use a radio checkbox.
Style the label for the radio underneath the button so that when the button is pressed the checkbox is also pressed.
Then you use the code below
.checkbox:checked ~ .background{
opacity:1
width: 100%
}
This code simply states IF the checkbox is CHECKED then open up the background ELSE leave it as it is.
css files do not support conditional statements.
If you want something to look one of two ways, depending on some condition, give it a suitable class using your server side scripting language or javascript. eg
<div class="oh-yes"></div>
<div class="hell-no"></div>
There is no native IF/ELSE for CSS available. CSS preprocessors like SASS (and Compass) can help, but if you’re looking for more feature-specific if/else conditions you should give Modernizr a try. It does feature-detection and then adds classes to the HTML element to indicate which CSS3 & HTML5 features the browser supports and doesn’t support. You can then write very if/else-like CSS right in your CSS without any preprocessing, like this:
.geolocation #someElem {
/* only apply this if the browser supports Geolocation */
}
.no-geolocation #someElem {
/* only apply this if the browser DOES NOT support Geolocation */
}
Keep in mind that you should always progressively enhance, so rather than the above example (which illustrates the point better), you should write something more like this:
#someElem {
/* default styles, suitable for both Geolocation support and lack thereof */
}
.geolocation #someElem {
/* only properties as needed to overwrite the default styling */
}
Note that Modernizr does rely on JavaScript, so if JS is disabled you wouldn’t get anything. Hence the progressive enhancement approach of #someElem first, as a no-js foundation.
Changing your css file to a scss file would allow you to do the trick. An example in Angular would be to use an ngClass and your scss would look like:
.sidebar {
height: 100%;
width: 60px;
&.is-open {
width: 150px
}
}
While this feels like a bit of a hack, and may not work perfectly in all browsers, a method I have used recently combines the fact that CSS (at least in Chrome) seems to ignore invalid values set on properties, and we can set custom properties that fall back to their default value when invalid.
(Note: I haven't deeply tested this, so treat it as a hacky proof of concept/possible idea)
The following is written in SCSS, but it should work just as well in standard CSS:
.hero-image {
// CSS ignores invalid property values
// When this var is set to an image URL, the browser will ignore it
// When this var isn't set, then we will use the default fallback for the var, which is 'none'
display: var(--loading-page-background-image, none);
// This part isn't directly relevant to my 'if' example, but shows how I was actually using this custom property normally
background-image: var(--loading-page-background-image, none);
}
I'm setting the custom property from JavaScript / React, but it would likely work regardless of how you set it:
// 'true' case
const chosenLoaderUrl = "https://www.example.com/loader.png";
// 'false' case
//const chosenLoaderUrl = "";
// containerRef is just a reference to the div object, you could get this with
// jquery or however you need. Since I'm in React, I used useRef() and attached
// that to my div
containerRef.current.style.setProperty(
"--loading-page-background-image",
`url(${chosenLoaderUrl})`
);
When chosenLoaderUrl is set to my url, that url is an invalid value for the display property, so it seems to get ignored.
When chosenLoaderUrl is set to an empty value, it falls back to the default value in my var() statement, so sets display to none
I'm not sure how 'generalisable' this concept it, but figured I would add it to the other suggestions here in case it is useful to anyone.
Your stylesheet should be thought of as a static table of available variables that your html document can call on based on what you need to display. The logic should be in your javascript and html, use javascript to dynamically apply attributes based on conditions if you really need to. Stylesheets are not the place for logic.
You can use combination of jquery and css classes i.e. I want to change a font color of certain element depending on the color of the background:
CSS:
.h3DarkMode{
color: lightgray;
}
.h3LightMode{
color: gray;
}
HTML:
<h3 class="myText">My Text Here...</h3>
JQuery:
var toggleMode = localStorage.getItem("toggleMode");
if (toggleMode == "dark"){
$(".myText").removeClass("h3LightMode").addClass("h3DarkMode");
}else{
$(".myText").removeClass("h3DarkMode").addClass("h3LightMode");
}
No you can't do if in CSS, but you can choose which style sheet you will use
Here is an example :
<!--[if IE 6]>
Special instructions for IE 6 here
<![endif]-->
will use only for IE 6 here is the website where it is from http://www.quirksmode.org/css/condcom.html , only IE has conditional comments. Other browser do not, although there are some properties you can use for Firefox starting with -moz or for safari starting with -webkit. You can use javascript to detect which browser you're using and use javascript if for whatever actions you want to perform but that is a bad idea, since it can be disabled.
Related
I am trying to implement dark mode in my app.
The idea is to add this to the root element:
<div id="dark">
And then this in CSS:
#dark {
background-color: #1A1A2E;
}
And then in Css, customize each dom element by using classes. For example, here I will work on cards:
#dark .card-body {
background-color: #16213E !important;;
}
#dark .card-header {
background-color: #0F3460 !important;
}
Now, this works perfectly fine.
But, with Modals, it does not work. I think it's because Modals are not rendered initially so for some reason the dark style does not apply to them.
What worked though is adding id="dark" to each modal:
#dark .modal-header {
background-color: #0F3460 !important;
}
#dark .modal-body {
background-color: #16213E !important;;
}
#dark .modal-footer {
background-color: #16213E !important;;
}
<Modal
// dark doesn't get applied automatically for modals because apparently modals are not rendered in the beginning
id="dark"
isOpen={this.state.isModalOpen}
toggle={this.toggleModal}
>
<div className="modal-header">
But, it'll be a pain to apply this to every single modal.
One solution mentioned here:
Modal should be the descendant of a tag which has id="dark". It is
loaded by the script right below the script tag and you are trying to
put 'dark' id on some div tag and the modal doesn't lie inside it,
thus the CSS selector not targeting it.
So, you need to put id="dark" on the body tag.
This solves the modals issue.
But, the problem is in my original implementation of dark mode, I am controlling that id in the root component like this:
// Root component
<div id={this.state.should_enable_dark_mode ? "dark" : "default"}>
And should_enable_dark_mode is managed like this:
manageDarkMode() {
window.addEventListener("storage", () => {
console.log("change to local storage!");
let should_enable_dark_mode = localStorage.darkMode == "true";
this.setState({
should_enable_dark_mode,
});
});
}
So the problem with the solution mentioned above is that I couldn't find a way to control the body tag from the react app. And I am not sure if it's a good thing to do.
What do you think I should do?
I see in the comments to your original question that you decided to just modify the body element in the browser DOM, which will probably work fine since the body element is not controlled by React and will likely not be changed by any other code.
I would however like to suggest a few improvements that makes it at bit less dirty:
use a data attribute like data-display-mode="dark" as a target for your CSS selectors instead of the ID. IDs are supposed to be stable and other tools and libraries (e.g. UI test tools) might rely on this.
use the Modal.container property to attach your Modals to the App element (the React-controlled global parent div defined in your React code, which you can control, not the app-root-div in index.html). Then set your data-display-mode attribute here by React-means. This way you will not bypass the virtual DOM.
use CSS custom properties for defining your colors, and then define all dark mode modifications in one place. Don't spread your dark-mode-styling code across multiple class selectors - you will have a hard time maintaining this.
Is there any problem creating a CSS class like this:
[test] { font: 13px; }
and use it in an HTML attribute as this:
<div test></div>
Would the performance in some browsers be affected by using this method?, I've tested it with Mozilla Firefox and Google Chrome and they seem to work with no problems.
Your custom attributes are not valid HTML. You must use data-* attributes if you want to put custom data on your elements. This makes what you are doing bad practice.
In addition, there are CSS classes already that should meet your needs, unless there is more to your question than you have described.
While there is no problem in applying styles this way, and sure it does work in the browsers, you have to understand that this is not a standard way of applying styles.
Since you have also asked from a 'practice' perspective, then, yes, this surely is not the right practice. The idea is: HTML is used to define the elements to be shown within the browser window, CSS is used to apply any styling that needs to be applied on these elements and JavaScript is used to perform any 'action' on it. So, from a practice perspective, this surely is bad practice!
On another note, why the reluctance to create a class and apply it on the div? After all, this class can be reused as and when required. If you need it only once, then why not create an id selector?
HTML:
<div class="rightApproach">The right way of applying styles</div>
CSS:
.rightApproach { color:Red; }
See this fiddle where you can see your approach as well as the correct way of applying styles, be it class selector or id selector.
http://jsfiddle.net/JkRPt/
It's better to use classes. This way will not work in older browsers and it's not professional.
However it doesn't have any performance issues.
HTML:
<div class="test">
CSS:
.test { font:13px; }
its good to use classes. Example:
<div class="module accordion expand"></div>
/* All these match that */
.module { }
.accordion { }
.expand { }
While this could possibly result in a simple yes or no answer I'll go for it anyway
Consider the following example:
HTML
<html>
<head>
</head>
<body>
<div class="foo">
<span class="bar">Hello world!</span>
<p>Some really interesting text.</p>
</div>
</body>
</html>
CSS
html {
/* some css */
}
body {
/* some css */
}
div.foo {
/* some css */
}
div.foo span.bar {
/* some css */
}
div.foo p {
/* some css */
}
Will the order in which css rules appear, have any effect on how (fast) the browser can render the page? ( in this example it won't really matter, but consider a real website with loads of html and css )
So the above css script will render faster or easier for the browser than :
div.foo p {
/* some css */
}
div.foo span.bar {
/* some css */
}
div.foo {
/* some css */
}
body {
/* some css */
}
html {
/* some css */
}
Do browsers care?
Should we?
Read before asking:
Is this how you would structure your CSS stylesheet?
What's the best way to organize CSS rules?
How do browsers read and interpret CSS?
I can't speak to order of the rules as it relates to speed.
However, as CSS stands for Cascading Stylesheets I consider it a moot point as the order of your rules does matter. So you aren't necessarily at liberty to move them around freely. Unless of course you supply continually more specific selectors (i.e. html body div.foo), which I think would have performance implications. If nothing else in file size.
In the end, remember that premature optimization is the root of all evil. Furthermore, there are other things that will have greater effect on speed (minification, static domain, etc) than rule order. Not to mention there is something to be said for code readability.
It matters for the importance of your selectors, adding details such as classes or IDs or parent elements will increase the importance of that rule over others.
Also, it may or may not decrease the speed of the browser who have to interpret it, but for sure it will increase the size of your CSS file to download and possibly be cached (not all handheld devices cache files bigger than a specified size).
CSS selectors specificity
It's typically not a good practice to strict type your classes and ID's to a specific element type.
div.foo {}
Will only work for Div's. Then you can't reuse that style elsewhere unless it's a Div element.
.foo { /* Base Style */ }
div.foo { /* Specific to if a DIV is used */ }
This is a slightly better approach.
After some more testing and reading I came to the following conclusion, no, it does not matter. Even after some ‘extreme’ testing, I could not find anything that supports the idea that the order matters.
There were no 'flashed of unstyled content' or the likes, it just took way longer to load the page ( way way longer :D )
Tests I ran
I created a test page with 60.000 div elements, each having a unique ID attribute. Each of these ID’s had their own css rule applied to it. Below that I had a single span element with a CLASS attribute, which was also had a css rule linked to it.
These tests created a html file of 2MB with a corresponding css file of 6MB.
At first I attempted these tests with 1.000.000 divs and css rules, but Firefox did not approve and started crying, begging me to stop.
I generated these elements and their css with the following simple php snippets.
<?PHP
for ($i = 0; $i < 60000; $i++) {
echo "
#test$i {
position: absolute;
width: 1px;
height: 1px;
top: " . $i . "px;
left: 0;
background: #000;
} <br />
";
}
?>
And
<?PHP
for ($i = 0; $i < 60000; $i++) {
echo "
<div id=\"test$i\"></div>
";
}
?>
The result was put in a html and css file afterwards to check the results.
Mind you, my browser ( Firefox 5 ) really did not appreciate me playing around with this, it really had some issues generating the output, the occasional this program is not responding message was not afraid to show it's face.
These tests were ran on a localhost, ran by a simple XAMPP installation, it might be possible that external servers result in a different resultset, but I am currently unable to test that.
I tested a few variations on the above:
Placing the element before all the generated divs, in the
middle and at the end
Placing the span’s css definition before, in the middle or at the end
of the css file.
Oh and may I suggest: http://www.youtube.com/watch?v=a2_6bGNZ7bA while it doesn't exactly cover this question, it does provide some interesting details about how Firefox ( and possibly other browsers )work with the stuff we throw at it.
The order doesn't matter in loading speed, it only matters when the styles cascade down, so you can't move them around willy-nilly. Using IDs may be faster than using classes, but you can only have one ID on a page. The best way to speed it up would be searching for things that have a class but are only used once, and changing it to an ID.
I'd say it's always best to order them in hierarchical order - so HTML is top, followed by body, followed by it's child rules.
Is there a way to remove CSS styles from an submit button so that the default browser style is applied?
You can set the styles to the system values,
input.overridecss {
background-color: ButtonFace;
color:ButtonText;
}
jsFiddle
Here is a list of values you can override, there is probably a better list but I'm lazy.
[Edit] Here is the Specification which has been deprecated lol,
so here is the correct way I guess,
input[type=button] {
appearance:push-button; /* expected from UA defaults */
}
from Appearence
You can do something like this:
button {
padding:0;
margin:0;
border:0;
background-color:transparent;
}
Hows that?
Store styles that you're applying programatically in a CSS class. When you want to go back to default remove the class.
Well, if you dont mind to use jQuery, you can use following code to remove all styles and classes from submit buttons.
$('input[type="submit"]').removeClass();
$('input[type="submit"]').removeAttr("style");
This will remove all classes as well as inline styles, thus system default button style will be applied to your all submit buttons.
I found that because I had:
* { border: 0; padding: 0; }
etc etc.
in my code which affects submit buttons so I put this is instead:
*:not(input) { border: 0; padding: 0; } etc etc.
This seemed to fix it.
If you're DEVELOPING the site - just remove the rules from the CSS file.
If you so wanted to, you could use Javascript/JQuery to remove/reset them based on some sort of condition if thats what you're looking for, ie:
$("#myButton").css("background","");
And so on...
If you're USING the site, but didn't build it - then you can (depending on your browser - i'm looking at Firefox 4) disable all or partial CSS from rendering using the web developer toolbar options... but I don't know if you can apply that as the 'default' setting for every site you load.
Note, this is different than the older question How can I apply CSS on all buttons which are present in that page? because this is an already existing style. So given that a style, which we'll call "standard_label_style" already exists in an included CSS file, what can I do to say that all the labels on this page should have that style short of adding:
class="standard_label_style"
to each and every one? And yes, I know I could apply the styles ex-post-facto with a snippet of jQuery or JavaScript code. I'm just trying to learn how I'm supposed to do it with CSS.
Follow Up
I've gotten several comments that say just use syntax like this .standard_label_style, label... Unfortunately that does nothing like what I want. That would allow me to apply additional rules to the standard_label_style class, as well as rules to labels within this page, but would not allow me to apply that style to all the labels on this page. To see an example of this, here is a stylesheet and html to demonstrate. The label without a class will still not appear in red but that's what I'm hoping to have happen. I want to apply an existing class to all those labels on the page, not just the one with the class and without adding new styling on this page, the existing style should be the only style.
included.css:
.standard_label_style { color: red; }
test.html:
<html>
<head>
<link rel="stylesheet" type="text/css" href="included.css">
<style>
.standard_label_style, label { }
</style>
</head>
<body>
<label class="standard_label_style">Test Label</label><br/>
<label>Unclassed Test Label</label>
</body>
</html>
CSS doesn't really work like that.
You can apply a style to all labels directly:
label {
color: Lime;
}
or apply a class to all labels
.labelClass {
color: Lime;
}
<label class="labelClass"></label>
You can also have multiple selectors, so you could ammend your current style to be
.labelClass, label {
color: Lime;
}
What you can't do in standard CSS is something like
label {
.labelClass;
}
The good news is that there are a bunch of server side libraries which make CSS suck less and let you do exactly this kind of thing, see for example dotLess if you're using .NET which provides nested rules and a basic inheratance model.
To apply a style to every label on the page, use this CSS:
label {
/* styles... */
}
If you have an existing style (e.g. "standard_label_style") in the CSS already, you can apply that to every label:
.standard_label_style, label {
/* styles... */
}
This will affect every label through the site, so use with caution!
In your css file, can't you just put
.standard_label_style, label
{
//styles
}
.standard_label_style, label {
/* stuff */
}
I'm not sure you can... one possible workaround (feels a bit hackish though) is to attach the style to your body tag, then change the css to be this:
body.standard_label_style label{
//Your styles here
}
One of the most underused CSS tricks of all time: Give your bodies an id or class!
HTML:
<body id="standard_label_style">
<label>Hey!</label>
</body>
CSS:
#standard_label_style label{
the styles
}
will take the styles, while
HTML:
<body id="custom_label_style">
<label>Custom!</label>
</body>
Will not.
You are dealing here with CSS precedence. Declarations which are "more vague" (body tag, classes) are applied before declarations which are "less vague" (specific elements, inline CSS).
Thus your answer depends on how the stylesheet is defining label styles. If for example it says label {...}, then that's fairly specific, and your best bet is to use a more specific CSS style, see:
http://www.vanseodesign.com/css/css-specificity-inheritance-cascaade/ (good tutorial?)
CSS precedence
The level of "specificity" you need to override, as I said, depend on how specific your other stylesheet was. According to the link, "CSS embedded in the html always come after external stylesheets regardless of the order in the html".
There is also a chance that if you yourself define label {your custom css} that should work, if you import your stylesheet afterwards. It is what I would try first to see if it works. Have you tried this? What was the result?
Note that if you want to completely override the other stylesheet, you will need to also reset any CSS you are not using by settings its values to inherit or as appropriate.