Dealing with repeated selectors: Placing elements together or using classes? - css

Let say I have to repeat the color blue in my web page, what's most effective, time saving, and smart way of doing it?
Examples:
1. This example can mess up a little bit my css file.
#header, #content, #footer {
color: blue;
}
#header {
(other properties)
(other properties)
(other properties)
}
#content {
(other properties)
(other properties)
}
#footer {
(other properties)
(other properties)
(other properties)
}
2. With this example I'll end up modifying my html file more often.
css:
.default-color {
color: blue
}
#header {
(other properties)
(other properties)
(other properties)
}
#content {
(other properties)
(other properties)
}
#footer {
(other properties)
(other properties)
(other properties)
}
html:
<div id="header" class="default-color">
(content here)
</div>
<div id="content" class="default-color">
(content here)
</div>
<div id="footer" class="default-color">
(content here)
</div>

I'd prefer the first form. Adding a "default-color" class starts to move into the territory of adding style into your markup, and it's generally more flexible to keep them separate as much as possible. On the other hand, if you have a semantic class name you can add to all of those that makes sense, then that could work.
Otherwise, if you really do just want a "default" color, you can specify it on the html or div elements in your css, and just override it with more specific classes where you don't want elements to show up as the default color.

Consider authoring your stylesheets using SASS. This will allow you to manage duplication in a number of ways:
The simplest is to define a variable for your blue color and not worry about having to update multiple occurrences:
$color-corporate-base: #009
#header { color: $color-corporate-base; }
#content { color: $color-corporate-base; }
This will compile to regular CSS, putting the color values wherever they're referenced in your document:
#header { color: #009; }
#content { color: #009; }
You could use "mixins" to include rules into different selectors:
#mixin bold-color {
color: blue;
font-weight: bold;
}
#header {
#include bold-color;
background: black;
}
#content {
#include bold-color;
background: white;
}
This will compile to regular CSS, with the two included style rules in each selector. Of course, this creates duplication:
#header {
color: blue;
font-weight: bold;
background: black;
}
#content {
color: blue;
font-weight: bold;
background: white;
}
Even though that takes care of the duplication in your Sass stylesheet source making it easy to work with, the CSS output still has that duplication. (You could group the common styles with commas and put the different styles into their own selectors, but that's right back to your original question.)
There's a cool new feature of Sass that addresses this. It's called "selector inheritance". Check it out:
.bold-color {
color: blue;
font-weight: bold;
}
#header {
#extend .bold-color;
background: black;
}
#content {
#extend .bold-color;
background: white;
}
At a glance, this seems very similar to mixins, but look at the CSS output:
.bold-color, #header, #content {
color: blue;
font-weight: bold;
}
#header { background: black; }
#content { background: white; }
This lets you organize your selectors in your Sass stylesheet as you wish, and, you get the optimized output you want!

One way of doing it for standard compliant browsers would be to use !important.
Example:
div
{
color: blue !important;
}

I would prefer the first version, too. But remember that you can also use multiple classes within one element. So you could you something like:
.blue {
color: #00F;
}
.bold {
font-weight: bold;
}
<div class="blue bold">Text</div>

Related

What is right BEM approach to global class inheritance?

I recently started using BEM methodology and I'm confused about class inheritance, or rather - when we talk about BEM - some use cases of modifiers.
Let's look at this example, I have a simple element with few children
.b-content { width: 100%; }
.b-content__image { display: block; }
.b-content__date { font-size: 14px; }
.b-content__title { font-size: 30px; }
.b-content__text { font-size: 16px; }
Now I want to reuse my .b-content block with slightly different styles, so I use modifier .m-compact and now I'm not sure what approach is the right one (in BEM).
Whether I should append modifier class to all elements (which I find more valid according to documentation):
.b-content.m-compact { width: 50%; }
.b-content__image.m-compact { display: none; }
.b-content__date.m-compact { font-size: 12px; }
.b-content__title.m-compact { font-size: 24px; }
.b-content__text.m-compact { font-size: 14px; }
or should I append modifier only to the parent element:
.b-content.m-compact { width: 50%; }
.b-content.m-compact .b-content__image { display: none; }
.b-content.m-compact .b-content__date { font-size: 12px; }
.b-content.m-compact .b-content__title { font-size: 24px; }
.b-content.m-compact .b-content__text { font-size: 14px; }
I find this second method more logical, you know, since I'm writing cascading styles and in real world if I want to write e-mail to 10 people, I would write one and just add more recipients, but on the other hand I realize BEM is practically non-cascading approach.
So what should I use and why?
As you point out in the last lines of your question, when doing BEM you should avoid cascading so, as a corollary to this, you don't have to repeat the modifier where it isn't needed.
For your Modifier I'd write something like this:
.b-content--m-compact {
width: 50%;
}
In your example the Block and the Modifier set only the width, so this is a limited use case. In general it comes handy to use some kind of CSS preprocess to ease the code writing, e.g. in SASS:
.my-block
width: 100%
color: red
&--modifier
#extend .my-block
border: 1px solid red
which will results in:
.my-block, .my-block--modifier {
width: 100%;
color: red;
}
.my-block--modifier {
border: 1px solid red;
}
Modifier in BEM looks like this: .block_modName_modValue
You can add additional class - but it's not BEM. And also modifiers have a name and value.
Block in BEM set namespace
So you set default styles for blocks and all unique(that can be changed) place in css with modifiers. This way your styles don't messed up.
To do this you need:
Place common styles in block styles(.portfolio)
Place unique style(with modifiers) like this.(portfolio_theme_list)
In css you don't need to separate this(preprocessor will be needed).
.portfolio {
/* common styles */
&_theme_list {
/* modifiers style */
}
}
In BEM project-stub(template engine) it would look like this:
If you add modifier to block. Then compile(bemjson) to html.
{
block : 'portfolio',
mods : { theme : 'list' },
}
You will see this code
<div class="portfolio portfolio_theme_list">
</div>
You write elements correctly and understand that they need to be separated(without inheritence).
So now you need just define styles for your block with modifier(portfolio_theme_list).
You have 2 options:
1) If you have 2 different blocks - you need separate common and
unique styles. Unique styles place in styles with modified blocks.
2) If you have only 1 different block & you already have styles on
this blocks. Then you can override and don't separate common
styles(but it can cause pain if you add another modifier/instance)

Scoping CSS / Prepend selector with LESS

I have a chunk of CSS that I want to "scope" to a specific block of HTML. I'm generating a unique ID and then setting it on the block of HTML and then would like to wrap the chunk of CSS with the same ID so that those selectors can't match sibling or parent elements. I don't know the contents of the chunk of CSS. Given a chunk of CSS:
.container {
background-color: black;
}
.container .title {
color: white;
}
.container .description {
color: grey;
}
I need it to come out like this:
.theme0 .container, .theme0.container {
background-color: black;
}
.theme0 .container .title, .theme0.container .title {
color: white;
}
.theme0 .container .description, .theme0.container .description {
color: grey;
}
Is there any way to do this with LESS? The first selector is easy, just wrap the CSS chunk with '.theme0 {' + cssChunk + '}'. But I haven't been able to figure out a way to prepend '.theme0' to all of the selectors without the space.
EDIT:
So I should clarify that our intentions are to build such a system into our build process / dependency system. We're attempting to scope a chunk of css to a react component. We have a couple different approaches we're trying out, this is just one of them. Point is, the CSS and HTML we're trying to scope could be anything, we have no control or knowledge of it. The first pattern can easily be achieved by prepending .uniqueID { and appending }. This gives .uniqueID .someSelector {}. I'm wondering if it's possible to do a similar thing but get .uniqueID.someSelector {}? Ideally without having to write the original chunk of CSS with knowledge of our scoping system.
Assuming the component styles are in a separate CSS file, i.e.:
// component.css
.container {
background-color: black;
}
.container .title {
color: white;
}
.container .description {
color: grey;
}
The wrapper code could be:
.theme0 {
#import (less) "component.css";
&.container:extend(.theme0 .container all) {}
}
in less you can nest selectors for selecting inside that element like:
.theme {
color: black;
.container {
color: blue;
}
}
This wil generate:
.theme {
color:black;
}
.theme .container {
color:blue;
}
Creating elements that are connected is easy enof:
.test#badge will select a class test width an id badge
In less this is dont with the & symbol. (this selects the starting property)
.test {
color: blue;
&#badge {
color:black;
}
}
Compiles to:
.test {
color: blue;
}
.test#badge {
color: black;
}
And for the final selector:
To get the output of .test, .container use the function: .test:extends(.container);
.test {
color: black;
&:extends(.conatiner);
}
.container {
color: pink;
}
Compiles to:
.test {
color: black;
}
.test, .container {
color: pink;
}
You can even extend multiple ones in a single line:
.test:extends(.oclas, .tclss);
and its wil work as abose only for both classes. So outputed selectors would be .test, .oclass and .test, .tclass

Howto use SASS parent selector for keeping declaration atomic in a structure with imports

As mentioned here it's possible to set properties based on e.g a class on a parent element.
I've tried it a while without luck to specify the color of a paragraph based on the sections background containing the paragraph to have all style definitions in the file for that paragraph to keep it atomic.
If I looked into the compiled CSS and saw something happens. I guess my filestructure broke things here because I created a lot of files and included them on the levels where these were needed.
Here's what I did:
// Main.scss
html{
body{
#wrapper{
#import "areas/section";
}
}
}
// _section.scss
section{
width:100%;
height:100%;
&.black{
background-color:#000;
}
&.white{
background-color:#fff;
}
#import "paragraph";
}
// paragraph.scss
p{
section.black &{
color:#fff;
}
section.white &{
color:#000;
}
}
And the generated outout looks like this:
section.white html body div#wrapper section p {
color: #000;
}
And I expect an output like this:
html body div#wrapper section.white p {
color: #000;
}
Is that possible or is my interpretation completely wrong?
The parent selector isn't a reference to the next level up, but the entire composed selector after all imports/extends/mixin calls are resolved.
.one {
.two {
.three & {
color: red;
}
}
}
The output will be this:
.three .one .two {
color: red;
}
In this example, & is equal to .one .two, not .two. It doesn't matter what method you use to nest your rules (extending, importing, or using mixins), the result is still the same.

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 */

Wrapping css without bloating css file

I was wondering if something like this can be done in CSS. I want to be able to group css so that I can I don't have to write it like this.
.wrapper .header {do: something};
.wrapper .nav .firstMenuItem {do: something};
[div id="wrapper"]
[div class="header"]
[div class="nav"]
[ul]
[li class="firstMenuItem">First Item</li]
[/ul]
[/div]
[/div]
[/div]
Instead, I would like to do something like this but I've never seen it being used like this
.wrapper
{
.header .nav {do:something;}
.header .nav .firstMenuItem
{
do: something;
}
}
You can do this with LESS and SASS
However, before going too far down this road I recommend you read a little about Object Oriented CSS. (Some good tips from people who have experience with large projects)
LESS example:
#header {
color: black;
.navigation {
font-size: 12px;
}
.logo {
width: 300px;
&:hover { text-decoration: none }
}
}
SASS example:
.error {
border: 1px #f00;
background: #fdd;
}
.error.intrusion {
font-size: 1.3em;
font-weight: bold;
}
.badError {
#extend .error;
border-width: 3px;
}
You can't do that with pure CSS, but you can use something like:
LESS
SCSS
Not with CSS alone, but you can for example use LESS which provides this kind of nesting.
I'm afraid that is just not possible in classic CSS. It is against the syntax.
There to exist interpreters for alternative syntaxes, which will just turn your syntax into valid CSS either at compile-time or run-time. You could look for or write one of those.
But if you want what you write to be valid CSS, this is just not possible.

Resources