SASS: generated CSS not optimal - sass

I am trying to learn SASS. I got this snippet working but the generated css is awful in my opinion. I would like all this css to go in te same .container{ }. Not three different as shown below.
SASS:
.container{
#extend %clearfix;
#extend %text-truncate;
#include border-radius(10px);
}
Genereted css:
.container{
...clear fix
}
.container{
...text-truncate
}
.container{
...clear border-radius
}
What I want:
.container{
...clear fix
...text-truncat
...clear border-radius
}

This is the nature of #extend. If you change your extend classes to ordinary classes, the way it works the way it does is revealed.
#mixin my-mixin() {
padding: 1em;
}
.a {
color: red;
}
.b {
border: 1px solid;
}
.foo {
#extend .a;
#extend .b;
#include my-mixin();
}
Compiles to:
.a, .foo {
color: red;
}
.b, .foo {
border: 1px solid;
}
.foo {
padding: 1em;
}
Using an extend only class simply suppresses the name from the output. If your extend classes are not intended for reuse, then they are better suited as a mixin.
See also: https://codereview.stackexchange.com/a/27910/26722

Related

How to stop #mixin in SCSS from duplicating CSS?

I want to use one CSS style for two classes with mixin, but when I use mixin the final result will be 2 classes with the same CSS.
I have shared my code example below:
#mixin btnhover {
background-color: $bg-cl-blc;
color: $txt-cl-ff;
}
.btn-base {
font-size: 15px;
&:hover {
#include btnhover;
}
}
.btn-otln {
font-size: 15px;
&:hover {
#include btnhover;
}
}
**OUTPUT CSS**
.btn-base:hover {
background-color: #000;
color: #fff;
}
.btn-otln:hover {
background-color: #000;
color: #fff;
}
This is how Sass works - it allows for better organisation of the code, but this code is then compiled, retaining functionality and not caring about other aspects.
If you really care about how the output code is structured, I would suggest to create a separate style for the classes with the hover effect:
#mixin btnhover {
background-color: #000;
color: #fff;
}
.btn-base {
font-size: 15px;
}
.btn-otln {
font-size: 15px;
}
.btn-base:hover,
.btn-otln:hover {
#include btnhover;
}
But in this approach, the use of mixin (and Sass) is questionable (in this exact case).
Generally, when you use Sass (or any other compiled language), you don't really care about the output CSS.
This won't be your answer, but I want to show you another way to make a mixin
#mixin btnhover($back, $color) {
background: $back;
color: $color;
}
When you use it, you can plug in the values
#include mixin btnhover($bg-cl-blc, $txt-cl-ff)
That way you can use the mixin over and over in different places with different values
Just discovered this recently myself, it's a concept called 'placeholders' in SASS syntax (see example below). I've done my best to apply it to your situation below....
Put this in your .scss file:
$bg-cl-blc: #ff211a;
$txt-cl-ff: #fff;
$btn-base-size: 15px;
%btnhover {
background-color: $bg-cl-blc;
color: $txt-cl-ff;
}
%btn-common {
font-size: $btn-base-size;
}
.btn-base {
#extend %btn-common;
&:hover {
#extend %btnhover;
}
}
.btn-otln {
#extend %btn-common;
&:hover {
#extend %btnhover;
}
}
CSS output will look like this
.btn-otln:hover, .btn-base:hover {
background-color: #ff211a;
color: #fff;
}
.btn-otln, .btn-base {
font-size: 15px;
}
Great article written up on this here:
https://dev.to/kemotiadev/are-sass-mixins-really-that-lightweight-and-what-are-placeholders-119i

Mixin in SCSS (properties of a class inside another one)

In LESS I could write something like:
.foo {
color: red;
}
.boo {
.foo();
background: blue;
}
To "include" properties of .foo class into .boo one.
What is the easiest and clean way to obtain a similar beaviour in SCSS?
How about trying like this,
mixins.scss
#mixin flex($x: center, $y: center) {
display: flex;
align-items: $x;
justify-content: $y;
}
custom.scss
.classname {
#include flex(flex-start, space-between);
color: red;
}
Use #include

SASS generates two separate rules for same class using extend and mixins

In this SCSS code, I'm using mixin btn-structure and extend %red-color to get all declarations under one class contrary to my expectation SCSS output two separate rules for the same class as shown in output below:
%red-color{
color: red }
#mixin btn-structure
($text-case: null, $text-shadow: null, $decoration: none ){
display: inline-block;
text: {
decoration: $decoration;
transform: $text-case;
shadow: $text-shadow }
}
.link-btn{
#include btn-structure($text-case: 'uppercase', $decoration: underline);
#extend %red-color
}
OUTPUT
.link-btn {
color: red;
}
.link-btn {
display: inline-block;
text-decoration: underline;
text-transform: "uppercase";
}
I don't want the SASS to output two separate rules belonging to same class how to get SASS to output one rule if that belongs to one class.
This is the actual behaviour and a use-case of Sass #extend.
Explanation
To make it clear, update your code as below
%red-color{
color: red
}
#mixin btn-structure ($text-case: null, $text-shadow: null, $decoration: none ){
display: inline-block;
text: {
decoration: $decoration;
transform: $text-case;
shadow: $text-shadow
}
}
.link-btn{
#extend %red-color;
#include btn-structure($text-case: 'uppercase', $decoration: underline);
}
.test-class{
#extend %red-color;
#include btn-structure($text-case: 'uppercase', $decoration: underline);
}
Which would compile as,
.link-btn, .test-class {
color: red;
}
.link-btn {
display: inline-block;
text-decoration: underline;
text-transform: "uppercase";
}
.test-class {
display: inline-block;
text-decoration: underline;
text-transform: "uppercase";
}
As you could see, #extend is used to "share a set of CSS properties from one selector to another", which can be clubbed together (.link-btn, .test-class). Whereas, #include is used to insert the styles where ever required, which is not clubbed.
Solution
For your requirement, you can resort to #include and declare a mixin #mixin red-color as below,
%red-color{
color: red
}
#mixin red-color{
color: red
}
#mixin btn-structure ($text-case: null, $text-shadow: null, $decoration: none ){
display: inline-block;
text: {
decoration: $decoration;
transform: $text-case;
shadow: $text-shadow
}
}
.link-btn{
#include red-color;
#include btn-structure($text-case: 'uppercase', $decoration: underline);
}
Output
And the compiled css will be,
.link-btn {
color: red;
display: inline-block;
text-decoration: underline;
text-transform: "uppercase";
}
Hope this helps.

How can I re-define an existing mixin whilst retaining the original output?

Let's say I have the following mixin:
#mixin foo {
color: red;
}
This mixin is imported in a library, so I don't want to touch the source code. I do however want to extend the functionality of the mixin, and add my own styles to it.
So I need a way to create a new mixin with the same name, whilst retaining the original output but allowing me to add new output, something like:
#mixin foo {
color: blue;
}
#mixin foo {
#include foo; // this is the original
font-size: 14px;
}
Of course the above will not do what I want, but is there something I can do?
I've been playing around and came up with this which seems to work:
#mixin foo() {
color: red;
}
%foo {
#include foo;
}
#mixin foo() {
#extend %foo;
font-size: 22px;
}
.foo {
#include foo;
}
You can extend/change code block of a Mixin using #content; while you have lines inside it by default.
#mixin foo(){
background:green;
border:solid 5px black;
#content;
}
div{
width:200px;
height:100px;
&.one{
+foo(){
border:0;
}
}
}
https://jsfiddle.net/Thielicious/hhb09b61/

How to extract common scss code from multiple files?

After converting a lot of redundant crappy css files into scss files, I have a bunch of scss files. I'm pretty sure there is a lot of common css repeated among these files and I would like to extract this code.
As an example, let's say I have this block of scss code (let's call it block A) :
.test {
color: white;
.toto {
background: red;
font-size: 12px;
}
}
And another block (that we'll call block B) :
.test {
color: black;
.toto {
background: blue;
font-size: 12px;
text-align: center;
}
}
I want to be able to extract the following common scss code from block A and B :
.test {
.toto {
font-size: 12px;
}
}
It seems like a simple task to do, but with a large list of long scss files, it's really painful to do it manually. After searching for a while I didn't find any tool for that.
An intermediary solution could be to convert sass code to a multi-dimensionnal associative array and to process arrays to find intersections, but I could not find any simple solution to do that either, so any help would be appreciated.
There are a few approaches but in this instance, I would opt for a variable:
$base-font-size: 12px;
.test {
color: white;
.toto {
background: red;
font-size: $base-font-size;
}
}
.test {
color: black;
.toto {
background: blue;
font-size: $base-font-size;
text-align: center;
}
}
Or you could add a toto mixin with some defaults and use that:
#mixin toto($background: red, $text-align: left, $font-size: 12px) {
.toto {
background: $background;
text-align: $text-align;
font-size: $font-size;
}
}
.test {
color: white;
#include toto();
}
.test {
color: black;
#include toto(blue, center);
}
EDIT: or use extend:
.font-size-12 {
font-size: 12px;
}
.test {
color: white;
.toto {
#extend .font-size-12;
background: red;
}
}
.test {
color: black;
.toto {
#extend .font-size-12;
background: blue;
text-align: center;
}
}

Resources