LESS mixin a variable class name - css

I am using Font Awesome 4.0.0, and want to do something like this in LESS:
.btn-github {
.btn;
.btn-primary;
margin-left: 3em;
i {
.#{fa-css-prefix};
.#{fa-css-prefix}-github;
.#{fa-css-prefix}-lg;
margin-right: 1em;
}
}
That doesn't compile with the error:
ParseError: Unrecognised input in - on line ...
Is it possible to accomplish this? It would certainly make a beautiful button for me.

There are at least 2 problems with what you are trying to do (for LESS >=1.6 see update bellow):
1) Unfortunately it is not possible to call a mixin using selector
interpolation.
With selector interpolation LESS expects the construct to be of
following format:
.#{selector-string} { property:value; }
(the interpolated selector can have also some static string pre or
post the interpolation)
so
.#{selector-string};
is Unrecognised by the LESS compiler. See more here:
How can I call a mixin by reference in LESS?
2) A ruleset with an interpolated selector gets directly printed to the CSS output and does not exist as a mixin that you could reuse in the LESS run
For example:
#foo: test;
.#{foo} {
length: 20px;
}
.bar {
.test;
}
will return:
Name error: .test is undefined
.bar { .test;}
See more on that here: LESS CSS: Reuse generated .#{name} class as a mixin
Possible solution for your problem would be redifinig the font awesome rules as some kind of reusable mixins (without using interpolation). Something like this:
#fa-var-github: "\f09b";
.fa-mixin() {
display: inline-block;
font-family: FontAwesome;
font-style: normal;
font-weight: normal;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.fa-mixin-lg() {
font-size: (4em / 3);
line-height: (3em / 4);
vertical-align: -15%;
}
.fa-mixin-icon(#icon){
#var: "fa-var-#{icon}";
&:before { content: ##var; }
}
i {
.fa-mixin;
.fa-mixin-lg;
.fa-mixin-icon(github);
}
If you don't really need the variables and just want to include the rules, the best way would be just to import the compiled CSS version of the FontAwesome (see answer here):
#import (less) 'font-awesome.css';
and then you can just use the CSS rules like LESS mixins or extend their selectors as you see fit and it should work perfectly.
Update:
As of LESS >= 1.6 rules with interpolated selectors can be accessed as mixins ... so the #2 limitation form above does not apply anymore (but you still can not call a mixin dynamically with interpolation). So you can simply call LESS mixins and variables from the imported font-awesome.less file like so:
i {
.fa;
.fa-lg;
&:before{
content: #fa-var-github;
}
}

Related

What does span {} do in CSS syntax?

I got some example CSS code (well written and working) with many span statements inside, that I modified for my use. What exactly they do? VS Code shows me as an error, but browsers don't complain, and I couldn't find any references in the CSS documentation, as if this syntax does not exist.
Example:
h2 {
letter-spacing: 2vw;
font-size: 2vw;
font-weight: bold;
text-align: center;
span {
display: block;
font-size: 8vw;
letter-spacing: -1vw;
}
}
VS code complains:
"code": "css-colonexpected",
"severity": 8,
"message": "colon expected",
"source": "css",
If I add colon it would be suggesting keys right away, and would not accept anything in curly brackets{}
Thanks
the brackets { and } define scope so that
body {
color: #000;
}
Would define that the color (text color) of the body element type (css query selector) would be #000 (which is hex for black)
however, if you have an element in an element like this using a precompiler such as less for css using the less syntax.
body {
color: #000;
span {
color: #FF0000;
}
}
this would do as the previous css did, but in less you can create a hierarchy
the body's color will be set to black as before.
and then any span child of the body element will have its color set to red (#FF0000)
CSS/LESS are used in conjunction with the HTML DOM object model.
You're correct that this syntax doesn't exist for CSS, as it doesn't support nested selectors like this.
The correct syntax would be:
h2 {
letter-spacing: 2vw;
font-size: 2vw;
font-weight: bold;
text-align: center;
}
h2 span {
display: block;
font-size: 8vw;
letter-spacing: -1vw;
}
This syntax is of course perfectly acceptable if you use a CSS preprocessor, like SASS or LESS for example. CSS preprocessors compile CSS written like you've done into standard CSS syntax, and add extra functionality, like using variables and conditional statements.
I think that modern browsers are probably capable of understanding syntax like this in certain situations, but if you want to use to this sort of syntax then using a preprocessor is a safer option to avoid errors.

What does "#extend must be used with a %placeholder" mean?

While linting the following SASS statements, I get #extend must be used with a %placeholder warning.
.reg-text {
color: #202226;
font-family: $font-page;
font-size: 17px;
line-height: 25px;
}
.reg-text-header {
#extend .reg-text;
font-weight: 600;
}
What does warning mean and how do I fix it. Afaik, .extend exists for the purpose of extending classes.
This is referring to an opinion that using #extend with normal CSS selectors is a bad idea.
I personally agree with this opinion, but it is an opinion nonetheless. Using #extend with any sort of selector is what the Sass spec allows, so I would possibly get in touch with the maintainers of your linter and request that the terminology in your error explains this.
If you use #extend to extend the definition of a selector, every time the selector is extended is is compiled to CSS that includes a reference of the selector for every time the #extend keyword is used.
If, however, you use #extend with placeholder selectors starting with % (A.K.A. "Silent Classes"), the functionality is much more in line with best practices. First off, any unused placeholder selectors are not even rendered to the final CSS (great for building reusable design libraries).
For example, if you have a block of reusable content within a CSS selector, consider converting it to use a placeholder selector instead:
.reg-text {
color: #202226;
font-family: $font-page;
font-size: 17px;
line-height: 25px;
}
.reg-text-header {
#extend .reg-text; // this is inefficient and causes specificity issues!
font-weight: 600;
}
// Instead, do this:
%reg-text {
color: #202226;
font-family: $font-page;
font-size: 17px;
line-height: 25px;
}
div.your-actual-selector-on-the-page .reg-text {
#extend %reg-text;
}
div.your-actual-selector-on-the-page .reg-text-header {
#extend %reg-text; // This compiles much neater and doesn't get in the way of specificity.
font-weight: 600;
}

SASS and Bootstrap - mixins vs. #extend

I'm using the SASS port of Bootstrap, and I'm wondering if there's any difference between using the pre-defined mixins and using SASS's #extend.
For instance, if I have:
<div class="wrapper">
Some content here....
</div>
Is there any difference between doing
.wrapper {
#include make-row();
}
and
.wrapper {
#extend .row;
}
?
If there's no difference, are there other mixins that aren't equivalent to a single #extend statement? If there aren't such mixins, why do the mixins even exist?
The big difference between #extend and a mixin is the way the css is compiled. It doesn't look like much in simple examples, but the differences and implications are significant and can be a real headache in the wild if used carelessly. #extend is a little bit like fools gold, looks great at first, but ...
Let's look at a simple example:
#extend
.row {
width: 50px;
}
.new-row {
#extend .row;
}
.another-row {
#extend .row;
}
compiles into:
.row,
.new-row,
.another-row {
width: 50px;
}
mixin
#mixin row() {
width: 50px;
}
.new-row {
#include row();
}
.another-row {
#include row();
}
compiles into:
.new-row {
width: 50px;
}
.another-row {
width: 50px;
}
A mixin includes the properties everywhere it is hit - copying them each time - whereas an #extend groups the selectors and defines the properties once. This isn't immediately obvious, because the difference is in the compiled css but it has some important implications:
Load order
With #extend the selectors will be grouped at the first point in the sass where they are encountered which can lead to some weird over-riding. If you define a selector and use #extend to bring in a property to and try to override a property defined earlier in your sass, but after the point at which the extended properties are grouped in the css then the override will not work. This can be quite perplexing.
Consider this logically ordered set of css definitions and the likely HTML: <div class='row highlight-row'></div>:
.red-text {
color: red;
}
.row {
color: green;
}
.highlight-row {
#extend .red-text;
}
compiles into:
.red-text,
.highlight-row {
color: red;
}
.row {
color: green;
}
So even though the sass ordering makes it look like the row colour would be red, the compiled css will make it green
Poor groupings
#extend can result in poorly grouped selectors in the resulting css. You can end up with thirty or forty unrelated things all sharing the same property for example. Using #extend for fonts is a good example of this.
Nesting
If you are using deeply nested sass (which is not good, btw) and you use #extend you will duplicate the fully nested selector for every #extend you use, resulting in bloated css. I've seen this a lot:
.selector-1 .selector-2 .selector-3 .selector-4,
.selector-1 .selector-2 .selector-3 .selector-4 a,
.selector-1 .selector-2 .selector-3 .selector-4 li,
.selector-1 .selector-2 .selector-3 .selector-4 td {
font-family: arial;
}
If you're new to SASS it pays to look at the compiled css.
Media queries
#extend do not work inside media queries, because media queries are not selectors.
Conclusion
My rule of thumb is to use an #extend over a mixin if you have no parameters and if you can reasonably define the #extend and share it amongst a few tightly related selectors that exist nearby in the sass, for example, in the same file that defines a sass module. Buttons are a good example of well used #extend:
%button {
padding: 10px;
}
.call-to-action {
#extend %button;
background-color: $green;
}
.submit {
#extend %button;
background-color: $grey;
}
The best article to help make the choice is here
PS, the % sign is a use of placeholder extends

Using FontAwesome wrapped in own css rule [duplicate]

I am using Font Awesome 4.0.0, and want to do something like this in LESS:
.btn-github {
.btn;
.btn-primary;
margin-left: 3em;
i {
.#{fa-css-prefix};
.#{fa-css-prefix}-github;
.#{fa-css-prefix}-lg;
margin-right: 1em;
}
}
That doesn't compile with the error:
ParseError: Unrecognised input in - on line ...
Is it possible to accomplish this? It would certainly make a beautiful button for me.
There are at least 2 problems with what you are trying to do (for LESS >=1.6 see update bellow):
1) Unfortunately it is not possible to call a mixin using selector
interpolation.
With selector interpolation LESS expects the construct to be of
following format:
.#{selector-string} { property:value; }
(the interpolated selector can have also some static string pre or
post the interpolation)
so
.#{selector-string};
is Unrecognised by the LESS compiler. See more here:
How can I call a mixin by reference in LESS?
2) A ruleset with an interpolated selector gets directly printed to the CSS output and does not exist as a mixin that you could reuse in the LESS run
For example:
#foo: test;
.#{foo} {
length: 20px;
}
.bar {
.test;
}
will return:
Name error: .test is undefined
.bar { .test;}
See more on that here: LESS CSS: Reuse generated .#{name} class as a mixin
Possible solution for your problem would be redifinig the font awesome rules as some kind of reusable mixins (without using interpolation). Something like this:
#fa-var-github: "\f09b";
.fa-mixin() {
display: inline-block;
font-family: FontAwesome;
font-style: normal;
font-weight: normal;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.fa-mixin-lg() {
font-size: (4em / 3);
line-height: (3em / 4);
vertical-align: -15%;
}
.fa-mixin-icon(#icon){
#var: "fa-var-#{icon}";
&:before { content: ##var; }
}
i {
.fa-mixin;
.fa-mixin-lg;
.fa-mixin-icon(github);
}
If you don't really need the variables and just want to include the rules, the best way would be just to import the compiled CSS version of the FontAwesome (see answer here):
#import (less) 'font-awesome.css';
and then you can just use the CSS rules like LESS mixins or extend their selectors as you see fit and it should work perfectly.
Update:
As of LESS >= 1.6 rules with interpolated selectors can be accessed as mixins ... so the #2 limitation form above does not apply anymore (but you still can not call a mixin dynamically with interpolation). So you can simply call LESS mixins and variables from the imported font-awesome.less file like so:
i {
.fa;
.fa-lg;
&:before{
content: #fa-var-github;
}
}

CSS - context used styling?

I thought that it was possible, but everyone tells me it's not.
I want context styling in my css file like:
div#foo {
h2 {
color: #F42
}
p.bar {
font-size: 12px
}
}
So that only h2 and p.bar in the div with id foo will be styled. Or is this only possible with LESS and other similar libs?
Thanks & kind regards,
Jurik
This is not possible with standard css, the 2 classes would need to be set like:
div#foo h2 {}
div#foo p.bar {}
This is not possible with pure CSS, that's why you should use SCSS or LESS (i suggest to use SASS/SCSS), which are CSS supersets
LESS/SASS-SCSS allows you to write dynamic CSS with ease, take a look at this comparision
check out COMPASS which is the main reason why I suggest you SASS/SCSS
It's possible, but as follows:
div#foo h2 {
/* styles go here */
}
div#foo p.bar {
/* styles go here */
}
What you have above is just a slightly altered version of:
div#foo h2 { color: #F42; }
div#foo p.bar { font-size: 12px }
I don't really see any gain to it.
Less let's you do pretty much what you described, as well as some other cool stuff like use variables in css etc.
Of course, once you let it compile, it'll just turn it into the valid CSS that has been suggested in the previous answers. Still worth a look IMHO.
yes but separated...
div#foo h2 {
color: #F42
}
div#foo p.bar {
font-size: 12px
}
but I would like too change a bit:
#foo h2 {
color: #F42
}
#foo p.bar {
font-size: 12px
}
you are using an ID so you don't need to say nothing before because ID's are unique
Its not possible using default CSS techniques.
But, by using sass and less however, it is possible.
The code in your question, works in both of the libraries above.

Resources