IE Conditional in Sass - css

Question
I use Paul Irish's IE Conditional Comments trick to target different versions of IE. In sass how do I apply one of these classes when nested in another class.
.container{
// I need to put a ie8 specific style here which is a .ie8 class applied to the body
}
I'd like to avoid doing this if possible (it's nice to be able to keep the properties together):
.container{}
.ie8{
.container{}
}
Is this possible?

I believe this is what you're looking for - using SASS's parent selector "&", you can do this:
.container {
.ie8 & {
// ie8 specific styles here
}
}

I am a little unclear as to what you are trying to do specifically. But If you are trying to do what I think you are trying to, then you could use a variable.
For example, lets say you only want to have your font color red in IE. You could do something like this.. Although I don't see how using SASS would be all that beneficial in this use case, unless of course you are trying to do something different.
SASS:
You can test this at: http://sassmeister.com/
$ieEightAndNine: "\0/";
.container {
color:unquote(red + $ieEightAndNine);
width:100px;
height:100px;
}
CSS:
.container {
color: red\0/;
width: 100px;
height: 100px;
}
TEST IN CHROME VS IE:
http://jsfiddle.net/3G48v/

Related

How to use CSS custom variables for properties

My stylesheets have large amounts of styles declared, often with a lot of repeated values. I read about variables in CSS to solve that problem.
I tried to use them, but it is not working:
element {
--main-bg-color: brown;
}
body {
background-color: var --main-bg-color;
}
What am I doing wrong?
You did everything right, just keep the variables in (put variable here)
element {
--main-bg-color: brown;
}
body {
background-color: var(--main-bg-color);
}
var() notation works like a method
var(<custom-property-name>)
might consider putting your variables in a :root selector...
:root {
--main-bg-color: brown;
}
/* The rest of the CSS file */
body {
background-color: var(--main-bg-color);
}
:root is similar to global scope, but the element itself (ie body { --myvar: ... }) or ancestor elements (ie html { --myvar: ... }) can also be used to define variables
Refer to MDN reference page. A brief, to use custom variables you need to place them inside :root selector:
:root {
--main-bg-color: brown
}
In order to use it in another selector yo use var():
body {
background-color: var(--main-bg-color)
}
For me, the problem was that #charset "UTF-8"; was not the very first characters in the css file, and this messed up the :root{--my-variable: large }.
You need to add var(--my-variable) when using the variables.
But that's not something you should use CSS custom properties (variables) for.
Bear in mind some browser can't understand CSS variables, most noticeably IE. So using any pre-processor instead will be better for compatibility, as they are compiled to regular CSS values. Either SASS, LESS, POSTCSS... whatever floats your boat.
CSS custom properties are much more powerful than pre-processor ones, as they can be changed at runtime with javascript and be used in all sorts of awesome ways, but when you're using them as regular variables, pre-processor variables are always better for compatibility.
If you want to declare them globally, I would recommend to use it in:
* { --var : #colorName; }.
This has actually helped me in Angular application.

overwrite css items depening on className

I'm having problems with my CSS markup in my code.
I'm building a control and my plan is to add a standard class to it so it has a fixed layout and add any userdefined css classes behind it, to personalise the control. but during my tests I noticed a problem which I can't resolve.
when I have an element like this
<div class="test1 test2"></div>
and underlaying code in another stylesheet file.
.test1
{
width: 200px;
height: 200px;
background-color: red;
}
.test2
{
background-color: yellow;
}
then it doesn't matter if I put test1 first or test2. the div will always be yellow only because test1 is written last on the css file.
if I replace test2 with test1 in the css file itself then the div will always be red.
how can I make the background-color overwrite incase its added a second time depending on the order its written in the className itself?
I also want to take notice I don't want to force users to use the !important tag. I already know about this and yes that works fine but I need it without. Any ideas on how to resolve this issues is welcome. I'm open for alternatives
You could make it so .test2 when combined with .test1 becomes yellow
.test1.test2{
background-color: yellow;
}
a better way tough is not to work like this at all. have a read of this article instead. It explains a technique for CSS called BEM (Block, Element, Modifier) which is pretty awesome. When trying to modify a existing style it will look like:
.test{
width: 200px;
height: 200px;
background-color: red;
}
.test--warning{
background-color: yellow;
}
and your div will look like <div class="test test--warning">
You can twiddle the precedence of the class's selectors like this:
.test2[class*=test2]
{
...
}
This should make class test2 override other classes that have only class name selectors.
(sorry, this part is not correct)
If you want to lower test1's precedence, you could do it like this:
[class*=test1]
{
...
}
(I haven't tested this, you might need to name it *[class*=test1] instead)
I been researching for a long time and posted here because I couldn't find a good answer. thx to the answers and responses here I was able to find an article over the problem I'm facing here CSS howto
What I'm trying to do is not possible because of the order css in generated. What I wanted is my css to work between browser default and external or internal stylesheets. I will look for an alternative solution to my project.

removing item from many css selectors

I have a vague memory, but can't find anything on it, about being able to use a keyword "with" or "like" to do something similar to the following.
using .class1{
#a1, #a4{color:#ffffff;}
#a2{color:#dddddd;}
#a3{color:#eeeeee;}
}
instead of having to write:
.class1 #a1, .class #a4{color:#ffffff;}
.class2 #a2{color:#dddddd;}
.class3 #a3{color:#eeeeee;}
The issue is that I'm including some html/css in a page and the css is screwing up the rest of the page. So, I'd like to modify the css so it only affect the small portion, rather than the whole page. I'm doing all this programmatically on a large number of pages, so it'd be much easier to just wrap all of the new css in something like "using .class1" rather than parsing through the css and add .class1 to the beginning of every selector.
Any ideas? thanks!!
There is no way to achieve what you want unless you use some CSS preprocessor like SASS. Here's how it would look when done using SASS:
.class1 {
#a1, #a4 {
color: #ffffff;
}
#a2 {
color: #dddddd;
}
#a3 {
color: #eeeeee;
}
}
Reference: little link.
Wrap the block of included HTML in its own ID like #overRideCSS
Then if you ever need to over-ride specific styles, you can preface your selector with that ID:
#overRideCSS <other selectors> {etc...}

CSS selector when :target empty

I need a css3 selector to target an element when the :target equals the id of the element (easy) or when the :target is empty (impossible?). It’s hard to explain, so let me give you a simple example.
div {
background: blue;
}
div:target, div:no-target {
background: red;
}
But of course the :no-target pseudo class doesn’t exist ;). Is there a way around this without using Javascript? Thanks in advance!
Sigh. I feel like I'm resurrecting a dead topic, but it needs a real answer.
It's possible to do this with CSS alone, just by using :last-child and a general sibling combinator, in the form of :target ~ :last-child:
.pages > .page:target ~ .page:last-child,
.pages > .page {
display: none;
}
/* :last-child works, but .page:last-child will not */
.pages > :last-child,
.pages > .page:target {
display: block;
}
The rules applies in the following steps:
hide all pages
show both targeted page and the last page
if a page is targeted, hide the last page (.page:target ~ .page:last-child)
(live example)
Edit: Apparently this is very similar to the accepted answer in an older, previously mentioned, related post.
There is a great answer for this over at default-target-with-css
It revolves around this trick that seems to have problems in iOS. It's been fixed in Safari, so maybe it'll be in iOS 5?
All I can think of is that you have some javascript that checks to see if the hash is empty. If so, it adds a class to the body tag called "noHash". Then, you can use the fact that there is the noHash class available in your CSS rules.
if (window.location.hash.length <= 1) {
document.body.className += " noHash";
}
Then, your CSS could be like this:
div {
background: blue;
}
div:target, body.noHash div {
background: red;
}
If there's any circumstance where a user might add a hash value after the fact, then you may have to watch for that to make sure the noHash class gets removed appropriately.
Note: you don't have to add the class name to the body tag. You can add it to any parent object that covers all the objects you wish to affect.
Why don't you use div:not(:target) or div:target:empty?

CSS Equivalent of the "if" statement

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.

Resources