Appending the parent selector to the end generates the incorrect result with Elixir/Libsass - laravel

I have the following SCSS:
.btn {
color: #000;
#at-root {
a#{&} {
display: inline-block;
}
}
}
I'm expecting the following CSS:
.btn { color: #000; }
a.btn { display: inline-block; }
But when I compile it using gulp-sass, I get this instead:
.btn { color: #000; }
.btn a.btn { display: inline-block; }

This appears to be a bug with Libsass, which is what gulp-sass compiles with. If you want to get the correct results, you'll need to switch to using the Ruby compiler for Sass.

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

Prevent combination of multiple selectors

I'm trying to group all my vendor-specific stuff into a placeholder selector like this:
%search-bar-placeholder {
color: red;
}
.search-bar::-webkit-input-placeholder {
#extend %search-bar-placeholder;
}
.search-bar:-moz-placeholder {
#extend %search-bar-placeholder;
}
.search-bar::-moz-placeholder {
#extend %search-bar-placeholder;
}
.search-bar:-ms-input-placeholder {
#extend %search-bar-placeholder;
}
And then it compiles to this:
.search-bar::-webkit-input-placeholder, .search-bar:-moz-placeholder, .search-bar::-moz-placeholder, .search-bar:-ms-input-placeholder {
color: red; }
How can I make sure Sass doesn't put all the selectors together ? Like this:
.search-bar::-webkit-input-placeholder {
color: red;
}
.search-bar:-moz-placeholder {
color: red;
}
.search-bar::-moz-placeholder {
color: red;
}
.search-bar:-ms-input-placeholder {
color: red;
}
When looking at Extend/Inheritance at sass-lang.com it seems that the selectors will always be comma separated. Even if you add another property, it will keep the shared properties in the comma separated list, and add another selector just for that overridden value.
The way I achieved what you want is by using a mixin. Though it's not really the purpose of a mixin, it does get the job done. Your style is still centralized and you can print it out in each selector using a one liner too.
#mixin placeholder-properties() {
color: red;
font-weight: bold;
}
.search-bar::-webkit-input-placeholder {
#include placeholder-properties();
}
.search-bar:-moz-placeholder {
#include placeholder-properties();
}
.search-bar::-moz-placeholder {
#include placeholder-properties();
}
.search-bar:-ms-input-placeholder {
#include placeholder-properties();
}
The result will the following.
.search-bar::-webkit-input-placeholder {
color: red;
font-weight: bold;
}
.search-bar:-moz-placeholder {
color: red;
font-weight: bold;
}
.search-bar::-moz-placeholder {
color: red;
font-weight: bold;
}
.search-bar:-ms-input-placeholder {
color: red;
font-weight: bold;
}
Here's a fiddle.

Sass / Scss: Changing the order of nested psuedo selectors for :before and :hover in generated CSS?

Given the following Sass:
div.test {
display: inline-block;
background-color: #ffffff;
color: #000000;
&:before {
& {
&:hover {
border: 1px solid salmon;
}
}
width: 25px;
height: 25px;
content: "";
}
}
The resulting CSS compiles to:
div.test {
display: inline-block;
background-color: #ffffff;
color: #000000;
}
div.test:before {
width: 25px;
height: 25px;
content: "";
}
div.test:before:hover {
border: 1px solid salmon;
}
What I am attempting to do is generate div.test:hover:before (the current output is before:hover).
NOTE: I am able to generate the expected CSS by using the following Sass:
div.test {
display: inline-block;
background-color: #ffffff;
color: #000000;
&:hover {
&:before {
border: 1px solid salmon;
}
}
&:before {
width: 25px;
height: 25px;
content: "";
}
}
However I would like to know if it is possible using the first nested approach or some modification of it.
The goal was to avoid having to repeat &:before if there was such a way to do so using Sass syntax. I am also OK with knowing it isn't possible.
While initially the plan was to have '&' available in SassScript as a string that could be manipulated so that you could insert values wherever you wanted, those plans have been abandoned for 3.3 due to complication. Unfortunately you'll have to wait a while to be able to do this. At the moment '&' is immutable and just means "whatever the selector chain up to this point is".
EDIT (2020.02.15):
it is now technically possible to achieve this with recent versions of dart-sass:
#use "sass:selector";
#mixin unify-parent($child) {
#at-root #{selector.unify(&, $child)} {
#content;
}
}
div.test {
display: inline-block;
background-color: #ffffff;
color: #000000;
&:before {
width: 25px;
height: 25px;
content: "";
#include unify-parent(":hover") {
border: 1px solid salmon;
}
}
}
Sources:
https://sass-lang.com/blog/the-module-system-is-launched
https://sass-lang.com/documentation/style-rules/parent-selector#advanced-nesting

Use a parameter as a tag in a mixin

How can I do that :
#mixin addMargin($el) {
$el {
margin-left: 5px;
}
$el:hover {
margin-left: 10px;
}
}
using sass ?
Thanks for your help
In a mixin, you can not only add properties directly to an element, but you can also add more rules:
#mixin addMargin {
margin-left: 5px;
&:hover {
margin-left:10px;
}
}
Note that you have to prefix the :hover with & so that we get this rule:
#something-with-the-mixin-applied:hover
instead of
#something-with-the-mixin-applied :hover
Use interpolation:
#mixin addMargin($el) {
#{$el} {
margin-left: 5px;
}
#{$el}:hover {
margin-left: 10px;
}
}
#include addMargin(h1);
But Yogu is right, you don't need it here. You may omit selectors, leaving only directives in your mixin, and apply the mixin inside a selector:
#mixin addMargin {
margin-left: 5px;
&:hover {
margin-left:10px;
}
}
h1 {
#include addMargin;
}

Using SASS to extend selectors with elements

I'm working on an SCSS stylesheet, and I have a rule that looks something like this:
.footer-link-row {
color: red;
ul& {
padding: 0;
}
}
I want the ul& line compile to the selector ul.footer-link-row. However, this selector returns a compiler error, and using a &ul compiles to .footer-link-row ul. What's the correct way to select something like this?
--Added--
To clarify, the eventual CSS I want out of this is:
.footer-link-row {
color: red;
}
ul.footer-link-row {
padding: 0;
}
You want something like the following:
ul {
padding: 0;
.footer-link-row {
color: red;
}
}
The ampersand is used to require that both selectors match
a { text-decoration: none;
&:hover { border-width: 1px }
}
// compiles to
a {
text-decoration: none;
}
a:hover {
border-width: 1px;
}
If you want the ul.footer-link-row try
ul {
&.footer-link-row {
padding: 0;
}
.footer-link-row {
color: red;
}
}
Your clarification indicates that you need two scopes.
ul {
&.footer-link-row {
padding: 0;
}
}
.footer-link-row {
color: red;
}

Resources