So I was writing up some code when I decided I wanted to make a variable for margin and padding, along with some other positioning too. But when I try I get errors.
This is what my code looks like:
//Positioning
#margin_t: margin-top:0;
#margin_r: margin-right:0;
#margin_l: margin-left:0;
#margin_b: margin-bottom:0;
#padding_t: padding-top:0;
#padding_r: padding-right:0;
#padding_l: padding-left:0;
#padding:_b: padding-bottom:0;
#center: text-align: center;
#left: text-align: left;
#right: text-align: right;
#relative: position: relative;
#justify: position: justify;
Can anyone give me their two-cents? Thank you!
As of LESS 1.7
You can include property values in variables by rulesets, like so (note bracketing and following semicolon; p.s. position: justify is not valid, I've changed it to absolute):
//Positioning
#margin_t: {margin-top:0;};
#margin_r: {margin-right:0;};
#margin_l: {margin-left:0;};
#margin_b: {margin-bottom:0;};
#padding_t: {padding-top:0;};
#padding_r: {padding-right:0;};
#padding_l: {padding-left:0;};
#padding:_b: {padding-bottom:0;};
#center: {text-align: center;};
#left: {text-align: left;};
#right: {text-align: right;};
#relative: {position: relative;};
#absolute: {position: absolute;};
A variable assigned ruleset is use much like a mixin (note the parentheses on the call), so:
.yourClass {
#relative();
}
Produces:
.yourClass {
position: relative;
}
The differences of a variable ruleset to a mixin are that you cannot pass parameters to a ruleset (directly anyway), but a ruleset can itself be passed as a parameter to a mixin. Also, variable rulesets will overwrite a previous definition (no matter properties defined), whereas mixins will merge property values. Rulesets work well for fixed values, like some of your items. They can be parametrized indirectly, something like so:
#margin_t: {margin-top: #tm;};
.yourClass {
#tm: 0;
#margin_t();
}
Varible rulesets actually work best for when one wants to pass to a mixin a group of properties or a single, unknown dynamic property. As an example of the latter, suppose you know you will want to set a single margin for an element, but depending on some context, you don't know which you want to set, so you want a single way to handle it. Then something like this can be done:
#margin_t: {margin-top: #value;};
#margin_r: {margin-right: #value};
#margin_l: {margin-left: #value;};
#margin_b: {margin-bottom: #value;};
.set-a-margin(#prop; #value: 0;) {
#prop();
}
.yourClass {
.set-a-margin(#margin_r; 10px);
}
.anotherClass {
.set-a-margin(#margin_b; 5px);
}
Produces:
.yourClass {
margin-right: 10px;
}
.anotherClass {
margin-bottom: 5px;
}
Basically, variable assigned rulesets just offer another way LESS can be used to code the way you may want to code. They can offer some functionality like mixins, with certain limitations and advantages different from those as related to variables.
Firstly, define your mixins like this:
.margin_t {
margin-top: 0;
}
.margin_b (#value: 0) {
margin-bottom: #value;
}
and then just use it!
body {
.margin_t();
.margin_b(15px);
}
You don't set the whole style. you would do #margin_t: 0;
Then use it
.myClass {
margin-top: #margin_t;
}
Related
Let me explain myself, i wanna do something like this in my code
$varible:{
display: inline-block;
width: 14px;
height: 14px;
}
.circle{
&:nth-child(1){
&::after{
$varible;
position:absolute;
...
}
}
}
Create a variable that contains a lot of attributes, and then use it as a global setting later, does anybody know if this is possible, or how I can perform an action like this?
Mixin is basically used to call a block of style but does not return any value unlike function in sass.
The #mixin directive lets you create CSS code that is to be reused throughout the website.
The #include directive is created to let you use (include) the mixin.
#mixin variable{
display: inline-block;
width: 14px;
height: 14px;
}
.circle{
&:nth-child(1){
&::after{
#include: variable;
position:absolute;
...
}
}}
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)
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.
I'm confused about double ampersand behaviour in LESS compiler.
Look:
.heading {
&&--type-small {
font-size: 15px;
}
}
Will be compiled to:
.heading.heading--type-small {
font-size: 15px;
}
And thats good.
But.
.wrapper {
.heading {
&&--type-small {
font-size: 15px;
}
}
}
Will produce:
.wrapper .heading.wrapper .heading--type-small {
font-size: 15px;
}
It looks weird. No?
Is there any advice to make this code works like:
.wrapper .heading.heading--type-small {
font-size: 15px;
}
Thanks =)
What happens when you use an ampersand in a nested rule is that the default nested structure gets ignored in the output selector and the ampersand acts as a placeholder for the complete list of outer selectors and will just insert all the parent rules all the way to the top of the hierarchy (the "path" for all nesting levels above) ... no way around that.
So using the first one - & will just join (concatenate) the nested selector to the whole list of outer selectors (appearing as if it just added it to the parent selector) and act as a combinator - see "Nested rules" at lescss.org. But then when you use the second ampersand - your selector will end up including all outer rules once again - the .wrapper and all rules in between will be added twice now. So, the behavior is not really strange. See also my answer to this question: "How to refer to two previous elements / tags / classes with LESS?" and for some more functionality of & see also seven-phases-max's comments below. Or find some examples of & being used as a "path" placeholder under "Advanced Usage of &" at lescss.org.
And to your concrete example:
I am not completely sure why you want to repeat the word "header" in the class name .header--type-small, if you are using it in addition to a class called .header ... I would just use additional classes such as .type-small, like so:
.wrapper {
//style for the wrapper
.heading{
//general style for the heading
&.type-small {
//style for the heading with class .type-small
font-size: 15px;
}
&.type-large {
//style for the heading with class .type-large ... and so on
}
}
}
with output CSS:
.wrapper .heading.type-small {
font-size: 15px;
}
but if you really really need the whole long string with the repeated names for some particular reason ... you could just do something like this:
.wrapper {
//style for the wrapper
.heading {
//general style for the heading
&.heading--type{
&-small {
//style for the heading with class .type-small
font-size: 15px;
}
}
}
}
with output CSS:
.wrapper .heading.heading--type-small {
font-size: 15px;
}
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.