SCSS Variables as #extend class - css

My idea is that I would like to write silent classes for input[type=text], input[type="password"] and input[type=submit]. I would then #extend them in a mixin by passing hem through as a variable.
My parser is throwing this error;
Syntax error: Invalid CSS after " #extend ": expected selector_sequence, was "$type;"
Here is my code;
%text {
(text styling)
}
%password {
#extend %text;
}
%submit {
padding: .5em;
background-color: $button-color;
border: none;
cursor: pointer;
color: white;
border: 1px solid darken($button-color, 20%);
&:hover {
#include transition;
background-color: darken($button-color, 10%);
}
}
#mixin input($type) {
margin-bottom: 1.5em;
margin-left: 0;
outline: none;
#extend $type;
}
Any help would be appreciated

try using variables interpolation
#extend #{$type};
Further information on SASS Reference

While Fabrizio's answer is formally correct, consider not going that way.
There's a great rule in programming of any kind: "keep it simple, stupid!" aka KISS.
Though SASS provides such advanced facilities as extends and mixins, it doesn't mean that you should use them as much as possible. Don't make your code complicated when you don't have to!
This code does exactly what you want: applying styles to input[...] selectors:
input {
margin-bottom: 1.5em;
margin-left: 0;
outline: none;
}
input[type=text], input[type=password] {
font-family: Verdana; // Text styles
}
input[type=submit] {
padding: .5em;
background-color: $button-color;
border: none;
cursor: pointer;
color: white;
border: 1px solid darken($button-color, 20%);
&:hover {
#include transition;
background-color: darken($button-color, 10%);
}
}
If you want to apply styles to custom classes/ids, consider this approach:
/////////////////
// Silent classes
/////////////////
%input {
margin-bottom: 1.5em;
margin-left: 0;
outline: none;
}
%text {
#extend %input;
font-family: Verdana;
}
%password {
#extend %text;
}
%submit {
#extend %input;
padding: .5em;
background-color: $button-color;
border: none;
cursor: pointer;
color: white;
border: 1px solid darken($button-color, 20%);
&:hover {
#include transition;
background-color: darken($button-color, 10%);
}
}
///////////////////////////
// Applying silent classes:
///////////////////////////
.some .weirdly .nested input[type=text] {
#extend %text;
}
.password {
#extend %password;
}
#the-submit-button {
#extend %submit;
}
Demo: http://sassbin.com/gist/5956909/

Related

SASS/SCSS - Making a selector that will "back out" to modify the parent of the selector

I would like to contain all relevant styles for a selector within a single code block, so that it can be easily referenced.
In my application, a selectors effective styles will be altered dramatically depending on the context in which it sits. For instance, let's assume this CSS:
.container.theme-dark .message
{
font-size: 16px;
background-color: black;
color: white;
}
.container.theme-light .message
{
font-size: 16px;
background-color: white;
color: black;
}
Then, imagine I have the following HTML:
<div>
<div class="container theme-dark">
<div class="message">Hello World</div>
</div>
<div class="container theme-light">
<div class="message">Hello World</div>
</div>
</div>
Right now with SCSS, I would create the relevant CSS like this:
.container
{
&.theme-dark
{
.message
{
background-color: black;
color: white;
}
}
&.theme-light
{
.message
{
background-color: white;
color: black;
}
}
.message
{
font-size: 16px;
}
}
I want to be able to generate that CSS using SCSS, with all of the relevant information for the .message element in one place. For instance (using a made-up $ operator that would do what I'm trying to accomplish):
.container
{
.message
{
font-size: 16px;
$.theme-light
{
background-color: white;
color: black;
}
$.theme-dark
{
background-color: black;
color: white;
}
}
}
Any ideas?
I'm thinking this might work, and is like what you're saying? (It would help me currently if you labeled each example as "Ideal CSS output", "Current SCSS, too many .message blocks", and "Ideal SCSS format")
.container
{
#at-root .message
{
font-size: 16px;
.theme-light &
{
background-color: white;
color: black;
}
.theme-dark &
{
background-color: black;
color: white;
}
}
}
With the #at-root there, it will generate .theme-light .message, which might be too permissive for some usages, so not the ideal solution...
https://codepen.io/anon/pen/ZMxjEq
Basically & gets replaced with the full tree-path, so .container .message, which without #at-root, will generate .theme-light .container .message, which does not work with the structure. Perhaps also consider this, which makes a reasonable compromise I would say:
.container
{
.message
{
font-size: 16px;
}
#at-root .message
{
.theme-dark
{
...
}
.theme-light
{
...
}
}
}
It's apparently a kind of hacky solution, but apparently works
This page might have some better guidance as well
This organization can be achieved if you use sass programatically:
$themes: light dark;
.container {
#for $i from 1 through length($themes) {
&.theme-#{nth($themes,$i)} {
.message {
font-size: 16px;
#if nth($themes,$i) == light {
background-color: white;
color: black;
} #else if nth($themes,$i) == dark {
background-color: black;
color: white;
}
}
}
}
}
This generates:
.container.theme-light .message {
font-size: 16px;
background-color: white;
color: black;
}
.container.theme-dark .message {
font-size: 16px;
background-color: black;
color: white;
}
The nested looping automatically groups the details at each level in the same block of code. This also scales to multiple levels of nesting. The critical point is that at inner loops you can reference the selectors of outer loops.
I eventually found this GitHub:
https://github.com/imkremen/sass-parent-append/blob/master/parrent-append.scss
Which I have adapted into this solution:
#function str-to-list($string, $separator: ' ', $startAt: 1)
{
$workStr: str-slice($string, $startAt);
$list: ();
$indexOfFirstSpace: str-index($workStr, $separator);
#if ($indexOfFirstSpace == null)
{
$list: ($workStr);
}
#else
{
$list: (str-slice($workStr, 1, $indexOfFirstSpace - 1));
$list: join($list, str-to-list($workStr, $startAt: $indexOfFirstSpace + 1));
}
#return $list;
}
#function getBase($appendix)
{
$parentSelector: str-to-list(#{&});
$pos: (length($parentSelector) - 1);
$selector: set-nth($parentSelector, $pos, nth($parentSelector, $pos) + $appendix);
#return $selector;
}
#mixin base($appendix)
{
#at-root #{getBase($appendix)}
{
#content;
}
}
Which I can then use like this:
.container
{
.message
{
font-size: 16px;
}
#include base(".theme-light")
{
background-color: white;
color: black;
}
#include base(".theme-dark")
{
background-color: black;
color: white;
}
}
which compiles into this:
.container .message
{
font-size: 16px;
}
.container.theme-light .message
{
background-color: white;
color: black;
}
.container.theme-dark .message
{
background-color: black;
color: white;
}

SCSS optimization

Below is my scss code, it gives expected output. But I feel it looks dirty that the -nrb repeats in both __red and __green, is there a way to simplify this?
$cell-header: '.cell-header';
#{$cell-header} {
&__red {
#extend .ui-grid-column-menu-button;
color: $red-cell-color;
background-color: $red-cell-bgcolor;
border: solid 1px $red-cell-color;
// no right border
&-nrb{
#extend .cell-header__red;
border-right: none;
}
}
&__green {
#extend .ui-grid-column-menu-button;
color: $green-cell-color;
background-color: $green-cell-bgcolor;
border: solid 1px $green-cell-color;
// no right border
&-nrb{
#extend .cell-header__green;
border-right: none;
}
}
}
Also, what is the correct way of extending the underlying class? Right now I have hard-coded the class name in #extend in -nrb, some keywords like this
You can group red and green:
$cell-header: '.cell-header';
#{$cell-header} {
&__red {
color: $red-cell-color;
background-color: $red-cell-bgcolor;
border: solid 1px $red-cell-color;
}
&__green {
color: $green-cell-color;
background-color: $green-cell-bgcolor;
border: solid 1px $green-cell-color;
}
&__red, &__green{
#extend .ui-grid-column-menu-button;
// no right border
&-nrb{
#extend .cell-header__green;
border-right: none;
}
}
}
I guess you could do some thing like this
$cell-header: '.cell-header';
#mixin headermixin ($cell-color, $cell-bgcolor) {
#extend .ui-grid-column-menu-button;
color: $cell-color;
background-color: $cell-bgcolor;
border: solid 1px $cell-color;
}
#{$cell-header} {
&__red {
#include headermixin($red-cell-color,$red-cell-bgcolor,.cell-header__red)
&-nrb{
#extend .cell-header__red;
border-right: none;
}
}
&__green {
#include headermixin($green-cell-color,$green-cell-bgcolor,.cell-header__green)
&-nrb{
#extend $cell-header__green
border-right: none;
}
}
}
Hope this helps
Thanks

Passing an extend as a mixin argument in SASS [duplicate]

My idea is that I would like to write silent classes for input[type=text], input[type="password"] and input[type=submit]. I would then #extend them in a mixin by passing hem through as a variable.
My parser is throwing this error;
Syntax error: Invalid CSS after " #extend ": expected selector_sequence, was "$type;"
Here is my code;
%text {
(text styling)
}
%password {
#extend %text;
}
%submit {
padding: .5em;
background-color: $button-color;
border: none;
cursor: pointer;
color: white;
border: 1px solid darken($button-color, 20%);
&:hover {
#include transition;
background-color: darken($button-color, 10%);
}
}
#mixin input($type) {
margin-bottom: 1.5em;
margin-left: 0;
outline: none;
#extend $type;
}
Any help would be appreciated
try using variables interpolation
#extend #{$type};
Further information on SASS Reference
While Fabrizio's answer is formally correct, consider not going that way.
There's a great rule in programming of any kind: "keep it simple, stupid!" aka KISS.
Though SASS provides such advanced facilities as extends and mixins, it doesn't mean that you should use them as much as possible. Don't make your code complicated when you don't have to!
This code does exactly what you want: applying styles to input[...] selectors:
input {
margin-bottom: 1.5em;
margin-left: 0;
outline: none;
}
input[type=text], input[type=password] {
font-family: Verdana; // Text styles
}
input[type=submit] {
padding: .5em;
background-color: $button-color;
border: none;
cursor: pointer;
color: white;
border: 1px solid darken($button-color, 20%);
&:hover {
#include transition;
background-color: darken($button-color, 10%);
}
}
If you want to apply styles to custom classes/ids, consider this approach:
/////////////////
// Silent classes
/////////////////
%input {
margin-bottom: 1.5em;
margin-left: 0;
outline: none;
}
%text {
#extend %input;
font-family: Verdana;
}
%password {
#extend %text;
}
%submit {
#extend %input;
padding: .5em;
background-color: $button-color;
border: none;
cursor: pointer;
color: white;
border: 1px solid darken($button-color, 20%);
&:hover {
#include transition;
background-color: darken($button-color, 10%);
}
}
///////////////////////////
// Applying silent classes:
///////////////////////////
.some .weirdly .nested input[type=text] {
#extend %text;
}
.password {
#extend %password;
}
#the-submit-button {
#extend %submit;
}
Demo: http://sassbin.com/gist/5956909/

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.

Can I use variables for selectors?

I have this variable:
$gutter: 10;
I want to use it in a selector like so SCSS:
.grid+$gutter {
background: red;
}
so the output becomes CSS:
.grid10 {
background: red;
}
But this doesn't work. Is it possible?
$gutter: 10;
.grid#{$gutter} {
background: red;
}
If used in a string for example in a url:
background: url('/ui/all/fonts/#{$filename}.woff')
From the Sass Reference on "Interpolation":
You can also use SassScript variables in selectors and property names using #{} interpolation syntax:
$gutter: 10;
.grid#{$gutter} {
background: red;
}
Furthermore, the #each directive is not needed to make interpolation work, and as your $gutter only contains one value, there's no need for a loop.
If you had multiple values to create rules for, you could then use a Sass list and #each:
$grid: 10, 40, 120, 240;
#each $i in $grid {
.g#{$i}{
width: #{$i}px;
}
}
...to generate the following output:
.g10 { width: 10px; }
.g40 { width: 40px; }
.g120 { width: 120px; }
.g240 { width: 240px; }
Here are some more examples..
Here is the solution
$gutter: 10;
#each $i in $gutter {
.g#{$i}{
background: red;
}
}
if it would be a vendor prefix, in my case the mixin did not compile. So I used this example
#mixin range-thumb()
-webkit-appearance: none;
border: 1px solid #000000;
height: 36px;
width: 16px;
border-radius: 3px;
background: #ffffff;
cursor: pointer;
margin-top: -14px;
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
input[type=range]
&::-webkit-slider-thumb
#include range-thumb()
&::-moz-range-thumb
#include range-thumb()
&::-ms-thumb
#include range-thumb()

Resources