#content VS normal additional rules - css

What is the difference between doing:
#mixin test($color: #000) {
border: 1px solid red;
color: $color;
}
#mixin extension($color: #000) {
#include test($color);
background-color: #eee;
}
or doing the following?
#mixin test($color: #000) {
border: 1px solid red;
color: $color;
#content
}
#mixin extension($color: #000) {
#include test($color) {
background-color: #eee;
}
}
is there any difference in the resulting CSS?
I cannot see the convenience of the #content directive.

The #content directive allows you to have a selector inside of your mixin and inject specific styles within that selector. The most common use case is a media query:
#mixin bp($i) {
#media (min-width: $i) {
#content;
}
}
.foo {
color: red;
#include bp(30em) {
color: green;
}
}
Other popular uses include abstracting keyframes declarations, placeholder selectors, or other selectors that require prefixes.

Related

SCSS, how to #extend Nested ampersand "prefix"?

The nested ampersand prefix doesn't get expanded with #extend
.firstClass{
color: green;
&-a{
color: red;
}
}
.secondClass{
#extend .firstClass;
}
The expected output would be
.firstClass, .secondClass{
color: green;
}
.firstClass-a, .secondClass-a{
color: red;
}
But the actual output doesn't have the .secondClass-a at all.
.firstClass, .secondClass{
color: green;
}
.firstClass-a{
color: red;
}
I found this is an intended behavior to use #extend https://github.com/sass/sass/issues/2154
But is there a workaround that can extend nested ampersand prefix?
Maybe the versions I worked on were older but I don't believe it was possible. You could change your properties to a mixin as such:
#mixin classStyle {
color: green;
&-a{
color: red;
}
}
.firstClass {
#include classStyle;
}
.secondClass {
#include classStyle;
}

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.

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.

Nested mixins or functions in SASS

Some body know how can i use nested mixins or functions in SASS?
I have something like this:
#mixin A(){
do something....
}
#mixin B($argu){
#include A();
}
yeah you already doing it right. You can call first mixin in second one. check this pen http://codepen.io/crazyrohila/pen/mvqHo
You can multi nest mixins, you can also use place holders inside mixins..
#mixin a {
color: red;
}
#mixin b {
#include a();
padding: white;
font-size: 10px;
}
#mixin c{
#include b;
padding:5;
}
div {
#include c();
}
which gives out CSS
div {
color: red;
padding: white;
font-size: 10px;
padding: 5;
}
As mentioned in the other answers, you can include mixins in other mixins. In addition, you can scope your mixins.
Example
.menu {
user-select: none;
.theme-dark & {
color: #fff;
background-color: #333;
// Scoped mixin
// Can only be seen in current block and descendants,
// i.e., referencing it from outside current block
// will result in an error.
#mixin __item() {
height: 48px;
}
&__item {
#include __item();
&_type_inverted {
#include __item();
color: #333;
background-color: #fff;
}
}
}
}
Will output:
.menu {
user-select: none;
}
.theme-dark .menu {
color: #fff;
background-color: #333;
}
.theme-dark .menu__item {
height: 48px;
}
.theme-dark .menu__item_type_inverted {
height: 48px;
color: #333;
background-color: #fff;
}
Scoping mixins means that you can have multiple mixins named the same in different scopes without conflicts arising.

Sass #extend base/default without also extending pseudo-classes?

I know I can #extend .foo:hover, but is there a way to #extend the .foobar base/default properties without also extending the definitions for pseudo-classes like :hover, :active, etc?
For example, how would I change the following such that .foobar extends only .foo's default state?
.foo {
& {
color:blue;
}
&:hover {
background-color: black;
}
}
.foobar {
#extend .foo;
&:hover {
//As is, I have to override. Any better way?
background-color: transparent;
}
}
(If there is no way to do this with Sass, is there a preferred way to achieve the same effect?)
You have to rewrite your selectors in such a way that you only extend exactly the part you want:
%foo {
color:blue;
}
.foo {
#extend %foo;
&:hover {
background-color: black;
}
}
.foobar {
#extend %foo;
&:hover {
background-color: transparent;
}
}
However, depending on how you are going to be extending/reusing your .foo class, the new #content directive might be the better way to go.
#mixin foo {
color: blue;
&:hover {
#content;
}
}
.foo {
#include foo {
background-color: black;
}
}
.foobar {
#include foo {
background-color: transparent;
}
}

Resources