Difficulties with scss BEM modifiers - html

I'm having a hard time understanding how to properly write scss with BEM naming conventions.
Here I have some HTML:
<div class="SomeBlock">
<div class="SomeBlock__someElement">text</div>
</div>
<div class="SomeBlock">
<div class="SomeBlock__someElement--greenBG">text</div>
</div>
<div class="SomeBlock">
<div class="SomeBlock__someElement--orangeBG">text</div>
</div>
And the follow scss:
.SomeBlock {
margin: 10px 0 0 0;
color: white;
width: 100px;
height: 50px;
background: red;
&__someElement {
background: blue;
text-align: center;
&--greenBG {
background: green;
}
&--orangeBG {
background: orange;
}
}
}
What I would expect to happen is to have 3 different blocks, all identical but with different colored backgrounds, and this is what happens excepted the text is not centered as I would expect it to be since my element style has text-align: center;
What am I misunderstanding? I've read some tutorials on scss with BEM, but I still do not understand.

Be careful when you reference parent selectors using & in Sass because it does not do what you think it does.
In normal nesting in SCSS, this:
a {
b {
/* styling */
}
}
generates a b { /* styling */ }.
However, when you reference parent selectors using &, this:
a {
&__b {
/* styling */
}
}
turns into: a__b { /* styling */ } // note that this is one class.
What BEM advocates is the use of a systematic way of naming classes to style your document, but manually writing out BEM is a nightmare. Sass parent selector referencing using & makes writing out BEM easy, but you still have to remember that you're only generating class names and not actually nesting when using the & in Sass.
What this all means is that in your case, you'll need to add each of the following classes for your various CSS rules to apply:
<div class="SomeBlock SomeBlock__someElement SomeBlock__someElement--greenBG">text</div>

Actually, you were a bit closer in using BEM accurately than #dippas. I would modify your code like this:
<div class="some-block">
<div class="some-block__some-element">text</div>
</div>
<div class="some-block">
<div class="some-block__some-element some-block__some-element--green-bg">text</div>
</div>
<div class="some-block">
<div class="some-block__some-element--orange-bg">text</div>
</div>
scss
.some-block {
margin: 10px 0 0 0;
color: white;
width: 100px;
height: 50px;
background: red;
&__some-element {
background: blue;
text-align: center;
&--green-bg {
background: green;
}
&--orange-bg {
background: orange;
}
}
}
Here's simplified outputted css to put things in perspective.
.some-block {
/* block styles */
}
.some-block__some-element {
/* element styles */
}
.some-block__some-element--green-bg {
/* element mod styles */
}
As a general rule, whenever you want to use a modifier you'll need to remember to add the element class an additional time with the modifier. So for your element you have a base class of '.some-block__some-element'. You'll need to add this to all the elements that need this class. Then use that same class and add it again to the element with the modifier. In your example, since you only added that base class to the first occurrence of the three elements, css will naturally only style that one with background: blue, and text-align: center.
Additionally, although you can technically get away with using uppercase class names, I would recommend using lowercase class names and separating multiword names with a single hyphen instead of using upper camel casing.

This is the best way to name classes accordingly to BEM methodology:
/* Block component */
.btn {}
/* Element that depends upon the block */
.btn__price {}
/* Modifier that changes the style of the block */
.btn--orange {}
.btn--big {}
Take a look at BEM 101 from CSS Tricks
So I would use it single classes to simplify.
.someblock {
margin: 10px 0 0 0;
color: white;
width: 100px;
height: 50px;
background: red;
}
.some__element {
background: blue;
text-align: center;
}
.green--bg {
background: green;
}
.orange--bg {
background: orange;
}
<div class="someblock">
<div class="someblock some__element">text</div>
</div>
<div class="someblock">
<div class="someblock some__element green--bg">text</div>
</div>
<div class="someblock">
<div class="someblock some__element orange--bg">text</div>
</div>

Related

How to use CSS Style one class inside another class but another class don't affect main class style

I used two classes .swap and .cont. How to use .swap class style so that it won't effect .cont style.
.swap{
background-color: red;
padding: 10px ;
}
.cont{
margin-top: 10em;
color: blue;
}
<div class="swap">
<div class="cont">
<div class="container">test</div>
</div>
</div>
using :not css
:not(X) {
property: value;
}
You can either use the :not(nameOfSelector) css rule, as stated by Prajapati Ghanshyam who posted it first, or, even simpler and safer (for older browser compatibility's sake), you can override the css rules previously set by .swap by doing:
<style>
.swap{
background-color:red;
padding 10px 10px 10px 10px ;
}
.cont{
margin-top: 10em;
color: blue;
/* OVERRIDE */
background-color: #acolorofyourchoice;
padding: 0;
/* END OVERRIDE */
}
</style>

SCSS + BEM style children structure when parent has modificator

Please is possible to set scss for element inside --rounded ? I do not wanna use .box__something, but I need to modify children that is depend on parent modifier
<div class="box">
<div class="box__something">Hello</div>
</div>
<div class="box box--rounded">
<div class="box__something">Hi</div>
</div>
.box {
&__something {
background: blue;
}
&--rounded {
background: green;
.box__something { // <<< Is some better selector?
background: pink;
}
}
}
Sass doesn't have any great built-in solutions to solve your issue, this is a problem that has been explored many times. You can however acheive the result you are after in a slightly un-elegant manner by using the & helper to join the classes that you wish to join. I have included a live example here.
While this does work, you must realise that if you want to style the .box--rounded class directly you must have it inside it's own class as illustrated below, you cannot use it with the trailing & class that we have placed &__something on.
I recommend you play around with my sassmeister gist and see what results you can come up with.
.box {
&__something {
background: blue;
}
&--rounded {
background: green;
}
&--rounded & {
&__something {
background: pink;
}
}
}
I hope this has solved your issue.
The modifier should be used not on the parent, and the child element .box__something
If I understand your problem correctly, I feel your pain! As soon as you nest a nested property & changes to the parent.
You can however cache the original class name as a variable like this:
$box: box;
.#{$box} {
.#{$box}__something {
background: blue;
}
.#{$box}--rounded {
background: green;
.#{$box}__something { // <<< Is some better selector?
background: pink;
}
}
}
The only problem with the method above is that you end up with a larger volume of compiled CSS. This renders to:
.box .box__something {
background: blue;
}
.box .box--rounded {
background: green;
}
.box .box--rounded .box__something {
background: pink;
}
To reduce the size of the output you could combine & with the variable method like so:
.box {
$box: &;
&__something {
background: blue;
}
&--rounded {
background: green;
#{$box}__something {
background: pink;
}
}
}
This renders to:
.box__something {
background: blue;
}
.box--rounded {
background: green;
}
.box--rounded .box__something {
background: pink;
}
That way you can change the class name in the variable and everything gets updated, I also think it reads a bit better.

Can one CSS block use another block?

Can I use something like this in css?
.bordered
{
border: 10px dashed yellow;
}
form input
{
use .bordered;
font-size: 10px;
}
Or how can this be achieved without writing each css code block to html element?
Well, you can always add class(es) to the input.
You could normalize/refactor your classes so that they are more generic (but do not overdo this). Example:
.bordered {
border: 10px dashed yellow;
}
.smaller {
font-size: 10px;
}
<form>
<input class="bordered">
<input class="smaller">
<input class="bordered smaller">
</form>
Fast answer:
.bordered, form input { border: 10px dashed yellow; }
form input { font-size: 10px; }
Solutions for re-usable code is to use CSS Preprocessor - LESS or SASS or you can create a new class and call it whatever you want and add styles to it.
Ten Reasons You Should Be Using a CSS Preprocessor - https://www.urbaninsight.com/2012/04/12/ten-reasons-you-should-be-using-css-preprocessor
References:
LESS
SASS
Unless you are using CSS preprocessors, you could do it like so:
.bordered,
form input {
border: 10px dashed yellow;
}
form input {
font-size: 10px;
}
or, if you want to avoid to list all selectors one by one, you could create a class with that style and add that class to your elements

LESS mixin apply to nested DIV

I have a nested div structure like this:
<div class="Button" id="StartButton" >
<div class="buttonIcon" id="startButtonIcon"></div>
<div class="buttonText" id="startButtonText">Start</div>
</div>
and a couple LESS mixins I use to format the parent div as a button shape, the icon as an actual image, and the text as special formatting like this:
.button-base() {
... LESS code here
}
.buttonIcon(#image) {
... LESS code
}
.buttonText() {
... LESS code
}
and here's my LESS structuring for the HTML:
#startButton {
.button-base();
#startButtonIcon {
.buttonIcon('img/icon_start_default.png', 'img/icon_start_hover.png');
}
#startButtonText {
.buttonText;
}
}
What I'd like to do is apply the hover selector in the .button-base() LESS mixin and have it change the image and text of the nested DIVs appropriately. I can't seem to figure out the right way to use the & selector in the parent Mixin.
I'm also open to restructuring the DIV group so that i can control the Icon & text from just 1 LESS mixin. I'm not sure how I would do that though, since i'm also such a beginner at HTML, LESS/CSS etc.
Any help is appreciated!
BTW, here's a jsFiddle that shows what I'm trying to accomplish. I know you can hard code the CSS, but I'm trying to avoid that and use best practices and automate as much as possible with the LESS code: http://jsfiddle.net/tLfqzq8c/3/
Here's what you loking for:
.Button {
width: 115px;
height: 30px;
border-color: #ececec;
border-width: 1px;
border-style: solid;
text-align: center;
vertical-align: middle;
line-height: 30px;
display: inline-block;
color: #666666;
background: #ececec url('http://res1.windows.microsoft.com/resbox/en/6.3/main/89ff52cc-8b6d-4a8e-bae3-5bfca40dcb59_18.png') no-repeat 10%;
}
.Button:hover {
color: white;
background-image: url('http://www.phiadariasoft.com/main/images/windows_icon.png');
}
Here's the html:
<div class="Button" id="StartButton" >
Start
</div>

How can I use :hover with multiple classes

I've got a css buttons style and some predefined colour styles. I use colour classes to colour things the same colour and a button style to make the buttons round.
How do I add a hover style to my buttons to change the colour to a lighter shade? I thought it would be as simple as .class class2:hover {etc} but it doesn't work for some reason.
Here's a fiddle I prepared to demonstrate:
http://jsfiddle.net/7n4Wy/
HTML
<p class="red button">Test</p>
<p class="blue button">Test</p>
<p class="red"> Not a button </p>
CSS
.red {
background: red;
}
.blue {
background: blue;
}
.button {
border-radius: 6px;
}
.button:hover .red:hover {
background: pink;
}
What you have is trying to match .red:hover that is inside .button:hover, which implies a nested element in your markup.
Since you're selecting the same element, you need to combine both classes with a single :hover:
.red.button:hover {
background: pink;
}
Updated fiddle
You can apply a CSS-rule to multiple selectors (classes like «.button», or states like «:hover») by separating them with a comma.
therefore just add a comma:
.button:hover, .red:hover {
background: pink;
}
Use following code JSFIDDLE
.button.red:hover {
background: pink;
}
To apply multiple classes, don't add a space (just use another period):
CSS
p.button {
border-radius: 6px;
}
p.red {
background: 6px;
}
p.button.red:hover {
background: pink;
}
HTML
<p class="button red">Hover Here</p>
The space is used to denote a child element. i.e. p.button red:hover would affect all elements with class red on hover that are wholly contained in parent paragraphs with class button.