I'm learning CSS and I found this syntax to group multiple selectors:
element-1, element-2 {
/* css declarations */
}
This means that the elements are in the same styling, so why don't we give them the same class? Is there any recommendations?
While there are probably many reasoning behind a general syntax decision, I could at least name one. Take the following example:
ul, li, p {
padding: 0; margin: 0;
}
Sometimes when you are resetting styles across different elements, you can use ,. You may group those using classes, but that would mean you need adding a class like .no-padding to each and every ul, li, p.
Not neat.
You can write the CSS rules without group of selectors, but you can minimize your CSS code with these groups. See the following example:
.one, .two {
color:red;
}
.two {
text-decoration:underline;
}
/** not optimized / no selector group */
.oneone {
color:red;
}
.twotwo {
color:red;
text-decoration:underline;
}
<p class="one">Hello World #1</p>
<div class="two">Hello World #2</div>
<p class="oneone">Hello World #1</p>
<div class="twotwo">Hello World #2</div>
Here is another illustration to join the two already featured (by Dai and sebastianbrosch)
Say you have a class that sets some values for an HTML element:
.someClass {
font-size:1.1rem;
color:#c00;
border: 2px solid #000;
padding: 1vh 1vw;
}
And just suppose you have another element (.someOtherElement)which you want to have the same font-size as someClass, and the same colour, same padding but no border?
Option 1:
Write everything out twice:
.someClass {
font-size:1.1rem;
color:#c00;
border: 2px solid #000;
padding: 1vh 1vw;
}
.someOtherElement {
font-size:1.1rem;
color:#c00;
padding: 1vh 1vw;
}
Option 2: Don't write everything out twice:
.someClass, .someOtherElement {
font-size:1.1rem;
color:#c00;
padding: 1vh 1vw;
}
.someClass {
border: 2px solid #000;
}
This more closely follows the DRY principles of programming and allows for immense flexibility, applying various rules to as many or as few identifiers as needed.
Related
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;
}
How can I simplify this SASS so that I only write .question-sector-answer the once? I need to apply different styles to the .question-sector-answer if the parent div has a class of both .question-row and .question-review. This currently seems unwieldy and I'm sure could be simplified and made more elegant:
.question-row {
border-bottom: 1px solid #ddd;
&.question-review {
.question-sector-answer {
padding-top: 30px;
}
}
.question-sector-answer {
padding: 15px;
}
}
I don't see how you can simplify it. You need to use 2 different styles for .question-sector-answer under different parents. Since it's impossible in css to access parent selector, you have no choice but do what you did (well, in SASS you kind of can - see below). Although my personal preference to always put more generic selectors on top and more specific ones to the bottom like so:
.question-row {
border-bottom: 1px solid #ddd;
.question-sector-answer {
padding: 15px;
}
&.question-review {
.question-sector-answer {
padding-top: 30px;
}
}
}
So in SASS you can access parent selector with & using it in certain way, but I don't think you can recreate your styles with it, the best I could come up with was this but it looks uglier than your original way of doing it, but you're welcome to play with it:
.question-row {
border-bottom: 1px solid #ddd;
}
.question-sector-answer
{
.question-row & {
padding-top: 15px;
}
.question-row.question-review &
{
padding: 30px;
}
}
You can read more about accessing parent selectors with & here
.question-row {
border-bottom: 1px solid #ddd;
}
.question-sector-answer {
padding: 15px;
.question-review & {
padding-top: 30px;
}
}
De-nesting here does two things: (1) creates terser, more flexible CSS and (2) allows the parent & selector. To compensate for the decrease in OOP, we slightly indent to imply subjugation. But in SASS you want to avoid the temptation to nest when not totally necessary, because nesting for OOP's sake tends to create more problems than it solves.
Getting to grips with LESS here but one thing is still a little unclear.
Lets say I have multiple color themes for my website, controlled by a class on the body tag. From this I can redefine the various colors for each element within each theme. Easy enough but fairly time consuming if I have a lot of elements to change... and a lot of themes. Every time I add a new theme I need to write out all the selectors again, with different color values.
I am basing my working so far on another post I found:
LESS.css variable depending on class
... However it still seems overly complicated for what I want to do in that I still have to write out all the selectors and include the mixin before dropping in the same CSS with the color variable.
I have created a CODEPEN HERE
I'd appreciate it if anyone had time to take a little look and advise me how I could approach this differently or how I could streamline this process.
Many thanks to anyone who helps out :)
Assuming you remain with wanting to theme it within one style sheet (and not multiple sheets as cimmanon noted in the comments), and assuming you are using LESS 1.3.2+, then the following code works to reduce the amount of duplication by setting up a loop through the classes that need theme changes.
Note that this does not work on Codepen (it is throwing an error uncaught throw #, perhaps because they are running an earlier version of LESS), but you can see it compiling correctly by putting the code into LESS's compiler.
LESS (based off your Codepen code with an added theme for demo)
//////////////////////////////////////////////////////
// CONSTANTS
#lightColour: #fff;
#darkColour: #000;
#lightBg: #fff;
#darkBg: #000;
#numberOfThemes: 3; //controls theme loop
//////////////////////////////////////////////////////
// MIXINS
//Theme Definitions by parametric mixin numbers (1), (2), etc.
.themeDefs(1) {
#lightColour: #f00;
#darkColour: #fff;
#lightBg: #f00;
#darkBg: #fff;
}
.themeDefs(2) {
//inverse of 1
#lightColour: #fff;
#darkColour: #f00;
#lightBg: #fff;
#darkBg: #f00;
}
.themeDefs(3) {
#lightColour: #cfc;
#darkColour: #363;
#lightBg: #cfc;
#darkBg: #363;
}
.curvy {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
//////////////////////////////////////////////////////
// GENERAL STYLING
* {padding: 0;margin: 0;}
html {text-align: center;}
h2 {padding: 20px 0;}
.box {
.curvy;
color: #lightColour;
background: #darkBg;
display:inline-block; width:10%; padding:20px 5%; margin:0 1% 20px 1%;
}
//////////////////////////////////////////////////////
// THEME BUILDING
.buildThemes(#index) when (#index < #numberOfThemes + 1) {
.theme-#{index} {
.themeDefs(#index);
color: #lightColour;
background: #darkBg;
.box {
color: #darkColour;
background: #lightBg;
}
}
.buildThemes(#index + 1);
}
//stop loop
.buildThemes(#index) {}
//start theme building loop
.buildThemes(1);
CSS Output (only showing the looped theme css for brevity)
.theme-1 {
color: #ff0000;
background: #ffffff;
}
.theme-1 .box {
color: #ffffff;
background: #ff0000;
}
.theme-2 {
color: #ffffff;
background: #ff0000;
}
.theme-2 .box {
color: #ff0000;
background: #ffffff;
}
.theme-3 {
color: #ccffcc;
background: #336633;
}
.theme-3 .box {
color: #336633;
background: #ccffcc;
}
For example, which is better:
Method 1 (name classes separately):
/* CSS */
.textbox-red,
.textbox-green {
padding: 10px;
border: 1px solid #CCC;
border-radius: 10px;
}
.textbox-red { color: #900; }
.textbox-green { color: #3c3; }
/*HTML*/
<div class="textbox-red"></div>
<div class="textbox-green"></div>
OR ------------
Method 2 (chain classes):
/* CSS */
.textbox {
padding: 10px;
border: 1px solid #CCC;
border-radius: 10px;
}
.textbox.text-red { color: #900; }
.textbox.text-green { color: #3c3; }
/*HTML*/
<div class="textbox text-red"></div>
<div class="textbox text-green"></div>
What is a better practice among the two?
My opinion is that you should use modular css -
You could also combine classes instead of linking them:
/*CSS*/
.textbox {
padding: 10px;
border: 1px solid #CCC;
border-radius: 10px;
}
.text-red { color: #900; }
.text-green { color: #3c3; }
/*HTML*/
<div class="textbox text-red"></div>
<div class="textbox text-green"></div>
That way you can reuse the red and green colors in cases when you want to have a red background without a textbox. This way you can re-use your code more and you have a loose coupling between your textbox and text-color
I personally would go with method 2. That way you can swap out text-red or text-green easily for text-blue or text-yellow and still keep the underlying style for your text. Basically, method 2 allows for more flexibility and maintainability, IMHO.
In my experience the modular approach gives you the most flexibility. The modular css pattern is also used in Twitter Bootstrap where flexibility is very important.
First better if you making style for IE6, because this browser dont support second method.
I'm using a dotLess 'mixin' like this:
.base-button-style
{
...
}
.specific-button-style
{
.base-button-style; //mixin
...
}
This works fine. But now I need to change the selector of the base style to give it a higher precedence by adding the tag name:
input.base-button-style
{
...
}
However, dotLess doesn't seem to like this, so the .less file can't be "parsed" at all. I've tried changing it to this with no better result:
input.base-button-style
{
...
}
.specific-button-style
{
input.base-button-style;
...
}
(That is, having the tag name in both the base style and where it is used as a mixin.)
Is there a way to make this work?
Note that I use both base-button-style and specific-button-style in my HTML.
I'm not sure if the mixins can have selectors, as they are effectively functions that are stripped out of the final code.
It might be better to nest your .specific-button-style under the .base-button-style like this:
.button {
display: inline-block;
outline: none;
cursor: pointer;
text-align: center;
text-decoration: none;
padding: .5em 2em .55em;
text-shadow: 0 1px 1px rgba(0,0,0,.2);
.border-radius(.5em);
.box-shadow(0, 1px, 2px, rgba(0,0,0,.2));
font-weight:bold;
font-size:15px;
#button-color: #faa51a;
&.edit, &.orange{
.button-normal(#button-color);
&:visited {.button-normal(#button-color);}
&:hover {.button-hover(#button-color);}
&:active {.button-active(#button-color);}
}
}
The &: operator for the .edit and .orange classes effectively produces .button.edit and .button.orange classes. The HTML element thus has class='button edit'. That will work on IE7+, and all the usual others.