Target elements with multiple classes, within one rule - css

I have some HTML that would have elements with multiple classes, and I need to assign them within one rule, so that the same classes could be different within different containers. Say I have this in my CSS:
.border-blue {
border: 1px solid blue;
}
.background {
background: url(bg.gif);
}
Then I have this in my HTML:
<div class='border-blue background'>Lorum Crap No-one Cares About Ipsum</div>
Can I target these within a single rule? Like this, for example, which I know doesn't work:
.border-blue, .background {
border: 1px solid blue;
background: url(bg.gif);
}

.border-blue.background { ... } is for when both classes are used together.
.border-blue, .background { ... } is for either class.
.border-blue .background { ... } is for where '.background' is the child of '.border-blue'.
See Chris' answer for a more thorough explanation. Also see W3 Docs on CSS Combinators

Just in case someone stumbles upon this like I did and doesn't realise, the two variations above are for different use cases.
The following:
.blue-border, .background {
border: 1px solid #00f;
background: #fff;
}
is for when you want to add styles to elements that have either the blue-border or background class, for example:
<div class="blue-border">Hello</div>
<div class="background">World</div>
<div class="blue-border background">!</div>
would all get a blue border and white background applied to them.
However, the accepted answer is different.
.blue-border.background {
border: 1px solid #00f;
background: #fff;
}
This applies the styles to elements that have both classes so in this example only the <div> with both classes should get the styles applied (in browsers that interpret the CSS properly):
<div class="blue-border">Hello</div>
<div class="background">World</div>
<div class="blue-border background">!</div>
So basically think of it like this, comma separating applies to elements with one class OR another class and dot separating applies to elements with one class AND another class.

Related

SCSS ampersand not working when trying to make modifiers for class names [duplicate]

I'd like to implement something like the BEM model in my Sass library. But I'm struggling to find a clean way to do this.
For example, I'd like to declare a 'base' style for a common element, and then extend it with useful variations:
.container {
margin: 10%;
background: #eee;
&-featured {
border: 2px solid #999;
}
}
The problem here is that the generated .container-featured class only contains the border property—Sass doesn't include the margin and background from its 'parent' class.
So you end up having to double up on classes in your markup to get the desired results:
<div class="container container-featured">
...
</div>
Is there some way to pull the properties from a parent class down into that modifier class, so you can get the same visual result just referencing the modifier class in your markup?
<div class="container-featured">
<!-- has margin, background, and border styles via just modifier class -->
</div>
I've tried using mixins to do this, but things get verbose and repetitive very quickly:
#mixins container {
margin: 10%;
background: #eee;
}
.container {
#include container;
&-featured {
#include container;
border: 2px solid #999;
}
}
Is there a simple, clean way of achieving this with Sass?
What you are looking for is the #extend directive. #extend allows you share a set of CSS properties from one selector to another. This means that you would only need to use the container-featured class.
Example
.container {
margin: 10%;
background: #eee;
&-featured {
#extend .container;
border: 2px solid #999;
}
}
compiles to:
.container,
.container-featured {
margin: 10%;
background: #eee;
}
.container-featured {
border: 2px solid #999;
}
You should use mixin in BEM not in Sass!
Mixins are just that - usage of several blocks and/or elements on the same DOM node.
A single DOM node can represent:
several blocks b-menu b-head-menu
a block and an element of the same block b-menu b-menu__layout
a block and an element of another block b-link b-menu__link
elements of different blocks b-menu__item b-head-menu__item
a block with a modifier and another block b-menu b-menu_layout_horiz b-head-menu
several different blocks with modifiers b-menu b-menu_layout_horiz b-head-toolbar b-head-toolbar_theme_black
Read more at: http://bem.github.io/bem-method/html/all.en.html, section Mixin.
Also you can use i-blocks (abstract blocks), so your .container will be .i-container, read more: http://bem.github.io/bem-method/html/all.en.html, section Naming conventions.
And with Sass you can implement i-block as
<div class="container-featured">
...
</div>
%i-container {
// abstract block styles
margin: 10%;
background: #eee;
}
.container-featured {
#extend %i-container;
border: 2px solid #999;
}
Without Sass, mixin in the BEM are made as follows:
<div class="i-container container-featured">
...
</div>
.i-container {
// abstract block styles
margin: 10%;
background: #eee;
}
.container-featured {
border: 2px solid #999;
}

Dealing with small variations in CSS?

Whats the best way of dealing with small variations in CSS?
For instance say if I have two buttons:
.btn-red .btn-blue
And I want each of the buttons next to one another but I want .btn-blue to have margin-left of 10 pixels.
I have a number of options that I could implement:
I could add an inline style to the .btn-blue element (but then you have issues of maintainability and readability if your conforming to a naming convention like BEM).
I could create a utility class that adds 10 pixels of margin (but then I'm falling into the trap of potentially having many one off utility classes, how about if I want an additional 20 pixels of margin on another item?)
I could extend .btn-blue and apply a different class (but that creates near enough the same problems as having a one-off utility class)
I could add 10 pixels directly to the .btn-green class but that conflicts with the Single Responsibility Principle.
I could target a wrapper class and using a descendent selector target .btn-blue but then I negate the usefulness of using something like BEM and fall into the world of specificity.
I realise the questions rather pedantic but this is one of the key issues as my CSS files grow that typically spirals out of control.
Say if I had the following...
SASS:
.btn {
padding: 10px 30px;
font-size: 16px;
border-radius: 3px;
border: none;
}
.btn-red,
.btn-blue {
#extend .btn;
color: white;
}
.btn-red {
background: red;
}
.btn-blue {
background: blue;
}
HTML:
<div class="btn-wrap">
<button class="btn-red">
Mr Red
</button>
<button class="btn-blue">
Mr Blue
</button>
</div>
I am honestly not quite certain about what you're trying to achieve, but could something like this help?
.btn-red + .btn-blue { /* Or [class*="btn-"] + [class*="btn-"], maybe */
margin-left: 10px;
}

How to select multiple ids that have a certain class in CSS

All I want to do is select multiple elements and with a certain class so that I don't have redundancy in my CSS file
#resp36, #physicalResp36, #nonResp36, #physicalNonResp36 .fieldStateError {
border: 1px solid #d6dbdc!important;
}
But the last element does not get the stlye while the others do. And I am not certain why that is happening.
Thank you in advance!
Spaces in a selector cause looking for child elements. You can select an element with multiple conditions by simply putting all selectors right behind each other:
#resp36.fieldStateError,
#physicalResp36.fieldStateError,
#nonResp36.fieldStateError,
#physicalNonResp36.fieldStateError {
border: 1px solid #d6dbdc !important;
}
Note that this is pretty much one of the most redundant things you could do in CSS, as classes are meant to unify such declarations into a single selector. Unless you were slinging the .fieldStateError class around, this should have the same effect as the code above:
.fieldStateError {
border: 1px solid #d6dbdc !important;
}
If all your elements have that class, you only need to use the class selector.
If you wanted to select the last id that also has that class, remove the space between class and id, because you are asking for a son of that id with that class.
you do not have a comma before ".fieldStateError".
Example:
#resp36, #physicalResp36, #nonResp36, #physicalNonResp36, .fieldStateError {
border: 1px solid #d6dbdc!important;
}
or remove the gap (<div id="#physicalNonResp36" class="fieldStateError">)
#resp36, #physicalResp36, #nonResp36, #physicalNonResp36.fieldStateError {
border: 1px solid #d6dbdc!important;
}

Confused about overriding CSS styles

I understand CSS basics, but I keep running into trouble with conflicting styles. Consider the following styles.
First, the default font color in my style sheets is black. I want that color applied to all picture captions - unless they're contained in divs with a class CoolL or CoolR...
.CoolL .Caption, .CoolR .Caption { color: #900; }
Now all the captions in the Cool series have brown text. But there are situations where I want the captions to have a black background with white text, so I created this rule:
.Black { background: #000; color: #fff; }
Now consider the following HTML. Class Caption by itself should have black text. However, this is inside a div with a class CoolR, so it displays brown text instead. But I added the class Black to the last div, which should change the background to black and the text color to white...
<div class="CoolR Plus Max300">
<div class="Shadow2">
<img src="">
<div class="Caption Black">Text</div>
</div>
</div>
In fact, the background is displaying black, but the text color is still brown.
I get these problems all the time, and the only way I can fix them is to write long, detailed styles, like this...
.Black, .Caption .Black, .CoolR .Caption.Black, .EverythingElseThatCouldBeBlack .Black { background: #000; color: #fff; }
What am I missing? Thanks.
I think you are over complicating things. This will become a maintenance issue as you add more styles. I would define separate classes and keep things simple. It's also important to understand CSS specificity.
.caption {
color: #000;
}
.cool-caption {
color: #900;
}
.caption-with-background {
background-color: #000;
color: #fff;
}
You could try :
.Black { background: #000 !important; color: #fff !important; }
There are a few fixes, but as previously recommended you should mark all of the settings you want to override previous ones with !important. With that, your code would look like this:
.Black {
background: #000;
color: #fff;
}
Also, not sure if you asked this, but you can apply CSS to all components by using the *, like so:
* {
//blahblahblah
}
you are defining the first case with a descendant selector which overrides the second class, which is merely a class. every answer given already will work but are entirely unnecessary. just add this to your style sheet:
.CoolR1 .Black, .Black{ background: #000; color: #fff;}
/** you could also chain your classes for specificity power **/
.Black.Caption{color:#fff}
that should do it. you can read more about selectors here:
http://docs.webplatform.org/wiki/css/selectors
I think that generally a more specific rule overrides a more general one, thus the more specific '.CoolR .Caption' is overriding the more general .Black. You'll probably be able to override this with !important, but a better style might be to reduce the complexity of your rules:
.Cool .caption { color: #900; }
.Cool .caption.black { color: background: #000; color: #fff; }
And put .L and .R in separate classes
.Cool.L { . . . } /* For things specific to CoolL, but not CoolR */
.Cool.R { . . . } /* and vice-versa */

CSS Selectors (or statement, containers, separator, etc)

Are there containers for CSS Selectors?
I'm simply curious if there's a more elegant way to do this without repeating the class:
#div1 .divClass, #div2 .divClass { color:cyan; }
This is what I had in mind, but I don't think there's a way to do it.
#div1,#div2 > .divClass { }
[#div1,#div2] .divClass { }
Short answer: No.
It seems a case where you can add a class for both divs.
<div id="div1" class="sharedClass"></div>
<div id="div2" class="sharedClass"></div>
.sharedClass > .divClass { color: cyan; }
Anyway, this question can have multiple answers. Consider looking at LESS, which extends CSS capabilities. Then you could do something awesome like this:
.divClass {
/* ... */
}
#div1 {
color: red;
border: 1px solid blue;
.divClass;
}
#div2 {
color: cyan;
border: 1px solid green;
.divClass;
}
Sounds like you're looking for a something like LESS, which is a stylesheet language which can be compiled into ordinary CSS. It might not do exactly what you're after in your specific case (but then again, it might, I haven't tried) but it sounds like it would be useful to you.

Resources