Using CSS prefix selector with SASS ampersand - css

In sass we can do some kind of class name concatenation with this:
//Sass
.button{
&-1{ background-color: red; }
&-2{ background-color: blue; }
}
//Result
.button-1{ background-color: red; }
.button-2{ background-color: blue; }
Can I somehow do concatenation on top of a prefix selector like this so that I don't have to use a base class or #extend:
*[class^="button-"]{
width: 20px;
height: 20px;
border: 1px solid black;
&-1{
background-color: red;
}
&-2{
background-color: blue;
}
}
I could achieve the same results with defining a base class and then adding specific styles after that like this:
.base-button{
width: 20px;
height: 20px;
border: 1px solid black;
}
.button{
&-1{ background-color: red; }
&-2{ background-color: blue; }
}
But I would then have to go and add that base class to all elements.
Another approach is using the #extend directive like this:
.button{
width: 20px;
height: 20px;
border: 1px solid black;
}
.button-{
&1{
#extend .button;
background-color: red;
}
&2{
#extend .button;
background-color-blue;
}
}
I guess my question is if there is a particular reason why sass doesn't support class concatenation when the parent selector is a class prefix selector. Isn't it safe to make the assumption that the prefix used in the selector can be used for concatenation when that parent selector has nested classes with &? Or am I just doing something wrong with my sass?
Thanks!

SASS does a objective, literal concatenation when you use &, so:
*[class^="button-"]{
width: 20px;
height: 20px;
border: 1px solid black;
&-1{
background-color: red;
}
&-2{
background-color: blue;
}
}
will generate:
*[class^="button-"]{
width: 20px;
height: 20px;
border: 1px solid black;
}
*[class^="button-"]-1{
background-color: red;
}
*[class^="button-"]-2{
background-color: blue;
}
which has invalid syntax, because a selector such as *[class^="button-"]-1 is not valid CSS.
You can create a mixin to get what you want. But frankly, these solutions should be last last resort, like selector by an attribute other than class name or id. Even that, just KISS to keep readability and maintainability.

Related

Property for specific selector

1. Summary
I have list of selectors, to which properties should always apply.
For some selectors must be additionally added another properties.
I can't find, how I can do it without duplicates.
2. MCVE
2.1. Expected CSS
.KiraFirst,
.KiraSecond,
.KiraThird {
color: red;
}
.KiraSecond {
background-color: yellow;
}
In example, I use class .KiraSecond 2 times. Can I get expected behavior without this duplicate?
2.2. Stylus
Live demo on stylus-lang.com
.KiraFirst
.KiraSecond
.KiraThird
color red
.KiraSecond
background-color yellow
This is compiled to expected CSS, but I still use .KiraSecond 2 times.
I don't understand, how I can not use duplicate. For example, syntax as this not compile to expected CSS:
.KiraFirst
.KiraSecond
background-color yellow
.KiraThird
color red
Result:
.KiraFirst,
.KiraSecond {
background-color: #ff0;
}
.KiraThird {
color: #f00;
}
3. Not helped
Stylus official documentation include Selectors section
Stack Overflow Stylus questions
Stylus GitHub issues
Maybe you can use basic class for all elements? For example - .Kira and if you need to specify something for other elements you can add extra class .KiraSecond or use .Kira:nth-child(2)
in your example it can be something like this
.Kira {
color: red;
}
.KiraSecond {
background-color: yellow;
}
or
.Kira {
color: red;
}
.Kira:nth-child(2) {
background-color: yellow;
}
You (can't)? and you shouldn't.
Duplicating that selector in that case is not a bad practice.
you are not duplicating the same property/value for many classes
you can clearly override specific property
you can clearly modify/change behaviour for specific class
e.g:
.class1, .class2, .class3 {
color: red;
background: yellow;
border: 1px solid;
}
.class1:hover {
color: blue;
}
.class2 {
border: 2px dotted;
}
.class3 {
color: pink;
}
What would be a bad practice in that case (with no selector duplication)
.class1 {
color: blue;
background: yellow;
border: 1px solid;
}
.class2 {
color: red;
background: yellow;
border: 2px dotted;
}
.class3 {
color: pink;
background: yellow;
border: 1px solid;
}

In Sass, what's the difference between the #mixin and #extend directives?

I just finished with the Sass guide.
The guide explains mixins:
..A mixin lets you make groups of CSS declarations that you want to
reuse throughout your site. You can even pass in values to make your
mixin more flexible.
and extend:
.. This is one of the most useful features of Sass. Using #extend lets
you share a set of CSS properties from one selector to another ..
It looks like 'extend' may be implemented in 'mixin' (it seems 'mixin' is extend of 'extend' :-) ).
// #extend
.message {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}
.success {
#extend .message;
border-color: green;
}
.error {
#extend .message;
border-color: red;
}
.warning {
#extend .message;
border-color: yellow;
}
// #mixin
#mixin message($color) {
border: 1px solid #ccc;
padding: 10px;
color: #333;
border-color: $color;
}
.success { #include message(green); }
.error { #include message(red); }
.warning { #include message(yellow); }
and even more because mixins have params.
But on the other hand the processed CSS is not exactly the same. But it will be same style effect on the DOM.
/* extend processed */
.message, .success, .error, .warning {
border: 1px solid #ccc;
padding: 10px;
color: #333; }
.success {
border-color: green; }
.error {
border-color: red; }
.warning {
border-color: yellow; }
/* mixin processed */
.success {
border: 1px solid #ccc;
padding: 10px;
color: #333;
border-color: green; }
.error {
border: 1px solid #ccc;
padding: 10px;
color: #333;
border-color: red; }
.warning {
border: 1px solid #ccc;
padding: 10px;
color: #333;
border-color: yellow; }
My question is how do these features differ?
When should I use one over the other?
From http://blog.nakulrajput.com/mixins-extends-and-placeholders/:
#mixin
Here is how mixins work. Definition and usage:
#mixin awesome {
width: 100%;
height: 100%;
}
body {
#include awesome;
}
p {
#include awesome;
}
The snippets above produce the following CSS:
body {
width: 100%;
height: 100%;
}
p {
width: 100%;
height: 100%;
}
To make things a little bit more interesting, we could make our mixin accept parameters. Even better, we are able to define default values if the mixin is called without arguments.
#mixin awesome($w: 100%, $h: 100%) {
width: $w;
height: $h;
}
body {
#include awesome(960px);
}
p {
#include awesome;
}
The result will be similar, but the width of the body is different.
body {
width: 960px;
height: 100%;
}
p {
width: 100%;
height: 100%;
}
If you use mixins, the styles in them are duplicated for each selector.
Mixins are very helpful if you need to change or calculate something in the final output, for example if you need to apply border-radius to several elements.
However, in some other cases there is a lot of duplicative code, which could be avoided if you use #extend.
**#extend**
.awesome {
width: 100%;
height: 100%;
}
body {
#extend .awesome;
}
p {
#extend .awesome;
}
It's similar, isn't it. In Sass it looks almost identical, but the CSS the result is:
.awesome, body, p {
width: 100%;
height: 100%;
}
Shorter than the version using a mixin. You can't pass parameters during the extending, but that's not the idea actually.
#extend should be used in those places where you want to share properties between the elements.
Well, Mixin is like function that can do some work and output processed result while extend is like pre-defined cop-paste code
In programming terms:
 #include is like calling a function with or without parameters
 #extend is like Inheritance
Function means, every time we call the function, the body of the function gets duplicated as we might pass dynamic information in the form of parameters. so you would get a Copy of the body.
Inheritance means, there is no duplication and we get a Reference instead of copy. so who ever extends that reference would get the same body.

Separating Stylus CSS Defintiions With Semicolons

Is it possible to separate Stylus definitions with semicolons?
Eg:
div.somclass
color blue; height 20px; border 1px solid blue;
Yep, see http://codepen.io/anon/pen/pJWzzw (view compiled CSS)
div.somclass {
color: #00f;
height: 20px;
border: 1px solid #00f;
}

Using LESS, is it possible to extend parametric mixins?

I'm new to LESS and I'm just experimenting with it, using version 1.5. I discovered the useful extend command, but I was wondering if that could be applied to parametric mixins as well as static ones. Apparently, this doesn't seem possible, based on my experiments:
This works
.some-mixin {
}
.child {
&:extend(.some-mixin);
}
This doesn't work and throws an "unexpected token" error:
.some-mixin(#color, #bgcolor) {
color: #color;
background-color: #bgcolor;
}
.child1 {
&:extend(.some-mixin(red, blue));
border: 1px solid blue;
}
.child2 {
&:extend(.some-mixin(red, blue));
border: 1px solid green;
}
.child3 {
&:extend(.some-mixin(red, blue));
border: 1px solid red;
}
Is this a current limitation of LESS, or am I using it incorrectly? Thanks in advance for the answers.
Edit - Added expected output, as per request
What I would expect makes more sense when there are more children extending the parametric mixin:
.child1,
.child2,
.child3 {
color: red;
background-color: blue;
}
.child1 {
border: 1px solid blue;
}
.child2 {
border: 1px solid green;
}
.child3 {
border: 1px solid red;
}
I'm not sure what you are trying to achieve (that is, I am not sure what you expect the :extend() code to actually do if it were extending the parameteric mixin). If your desire is to define the colors of .child, then using it as a straight mixin works:
LESS
.some-mixin(#color, #bgcolor) {
color: #color;
background-color: #bgcolor;
}
.child {
.some-mixin(red, blue);
}
CSS Output
.child {
color: #ff0000;
background-color: #0000ff;
}
This also makes .child itself a mixin for the red and blue color combination, which I think would have been a net result of the extension working if it had worked. That is, I would expect your second set of code to have produced something like this (theoretically; this does not actually work nor is it actually produced in LESS):
.some-mixin(#color, #bgcolor),
.child(#color: red, #bgcolor: blue) {
color: #color;
background-color: #bgcolor;
}
But these two are nearly equivalent as mixins (one has the added parameters):
/* theoretical mixin if extension worked */
.child(#color: red, #bgcolor: blue) {
color: #color;
background-color: #bgcolor;
}
/* code from straight use of .some-mixin in .child */
.child {
color: #ff0000;
background-color: #0000ff;
}
So that either of the above used like so will get the result of mixing in the child values to the new selector:
LESS
.test {
.child; /* or using .child(); */
}
CSS Output
.test {
color: #ff0000;
background-color: #0000ff;
}
No, currently this is not supported. But it's planned to be implemented in future versions.

Less nested rules get parent properties

Hello I am wondering is it possible to do something like this in less. I have this css:
.parent{display: block; color: red; border: yellow 1px solid;}
.parent a, .parent a.special-link{color: blue; border-color: green;}
I would write it in less like this:
.parent{
display: block;
color: red;
border: yellow 1px solid;
a, a.special-link{
color: blue; border-color: green;
}
}
And rules are ok but what if in further developing I have to add something to :hover but only for it eg. padding: 20px; What is the best way to do this? My first thought is that if there is some kind of workaround/hack/selector that allows to inherit all properties of parent.
I doubt I clearly understand your exact needs (":hover" of what? "only" for what "it"?)
But in general it usually goes like this:
.parent {
display: block;
color: red;
border: yellow 1px solid;
a {
// <a> properties:
// ...
&, &.special-link {
// <a> and <a.special-link> properties:
// ...
color: blue;
border-color: green;
}
&.special-link {
// <a.special-link> properties:
// ...
}
&:hover {
// <a:hover> properties:
// ...
}
/// etc. etc. etc.
}
}

Resources