Ampersand not working in :before in SASS - css

I'm building spritesheet buttons, something like this:
<a class="Button one"></a>
<a class="Button two"></a>
With style:
a {
// Add basic background and styling
background: transparent url("images/background_image.png") no-repeat;
// Add icon on top
&:before {
content: '';
display: block;
//....
background: transparent url("images/icons.png") no-repeat;
// (1)
&.one { #include tile(165px, 0, 0) }
&.two { #include tile(165px, 1, 0) }
}
// (2)
&.one:before { #include tile(165px, 0, 0) }
&.two:before { #include tile(165px, 1, 0) }
}
Now I want to add the variant styles, but (1) does not work, only (2). Is there no way to avoid repeating the :before?

If you take a look at the compiled CSS, you'd get something like this:
a:before.one { /* ... */ }
CSS pseudo-elements like :before and :after cannot have classes. If you want to make it shorter, one option would be to combine the classes:
a {
&.one, &.two {
&:before { #include tile(165px, 0, 0) }
}
}
But since you want to use different values for the mixin, I think #2 is the cleanest way to go.

Related

How to combine variable name and data-attr in SCSS?

Is there a way to do this in SCSS, to apply the background color $colorState0 dynamically to elem class width data-indx="0"?
SCSS:
$colorState0: rgb(0, 0, 0);
.elem {
background: $colorState(data-idx);
}
HTML:
<div class="elem" data-idx="0"></div>
You could use a mixin. The one below apply the background to the the element that has elem class and the given data-idx, but you can customise it to your need.
#mixin apply-background($idx) {
.elem[data-idx="#{$idx}"]{
background : rgb($idx, $idx, $idx);
}
}
#include apply-background(0);
You can try using this method :
$colorState0: rgb(0, 0, 0);
$colorState1: rgb(0, 0, 0);
.elem[data-idx=0] {
background: $colorState0;
}
.elem[data-idx=1] {
background: $colorState1;
}
and so on

SCSS/SASS dynamic background image based on class name

I was looking for a "sassy" way to do something like this:
.btn-save {
background: image-url('save.svg');
}
.btn-load {
background: image-url('load.svg');
}
.btn-back {
background: image-url('back.svg');
}
Is there a way I could grab the last part of the class name and pass it to a function to load the appropriate SVG icon? I was thinking it'd look something like:
#function load-svg($svg-name) {
background: image-url($svg-name + ".svg");
}
.btn-* {
// I'm not sure how to get the $svg-name here
load-svg($svg-name);
}
But I wasn't sure if that's possible to do in SCSS. Any help would be much appreciated, thanks!
If you want a DRY approach you could pass a list to a mixin
#mixin setSVGButton($svgs) {
#each $svg in $svgs {
.btn-#{$svg} {
background-image: url(#{$svg}.svg);
}
}
}
#include setSVGButton(('save', 'load', 'back'));
Do you mean something like this
#mixin btn($btn-type) {
.btn-#{$btn-type} {
background: image-url('#{$btn-type}.svg');
}
}
#include btn('save');
#include btn('load');
#include btn('back');

Referencing a sass/scss variable on the fly

I am trying to get a mixin done to achieve the following.
Im having a list of social buttons. They each share the same styles except the background-color and :hover states.
My current SASS approach. (will return invalid CSS error)
#mixin btn-social($network) {
.#{$network} {
background: $#{$network}; // trying to reference a global variable
&:hover, &:focus {
background: darken($#{$network}, $darken-modifier);
}
}
}
To render like this:
.facebook {
background: blue; // stored in $facebook
}
.facebook:hover, .facebook:focus {
background: darkblue; //darkend value above
}
I'm somehow lacking the right terms for a proper google search. I'd appreciate a push in the right direction.
Thanks for the help.
You can use a sass map to store the color variables and then find the right color using the name you pass into your mixin like so jsfiddle:
$colors: (
facebook: blue,
twitter: red
);
$darken-modifier: 100%;
#mixin btn-social($network) {
.#{$network} {
background: map-get($colors, $network);
&:hover, &:focus {
background: darken(map-get($colors, $network), $darken-modifier);
}
}
}
#include btn-social(facebook);
#include btn-social(twitter);
<a class="facebook">
facebook
</a>
<a class="twitter">
twitter
</a>
Edit: updated to include #TomOakley's suggestion below.
Please try the following:
#mixin btn-social($network, $color, $darkColor) {
#{$network} {
background: $color;
&:hover, &:focus {
background: $darkColor;
}
}
}
.foo {
#include btn-social('.facebook', blue, darkblue)
}
This compiles to:
.foo .facebook {
background: blue;
}
.foo .facebook:hover, .foo .facebook:focus {
background: darkblue;
}
Check out this reference for SASS interpolation.

The Sass ampersand and attribute selectors

I want to create a sass file that the selectors will be attribute selectors.
When I work with class selectors, in most of the cases I will do
.parent {
&-child {
}
}
which gives me the following css: .parent-child {}.
I want to achieve the same thing with attribute selectors:
[data-parent] {
&-child {
}
}
which I want to become: [data-parent-child] {}
someone knows how to achieve this? thanks.
You can use this mixin as a workaround to get the desired result.
#mixin child-attribute($child) {
$string: inspect(&);
$original: str-slice($string, 3, -4);
#at-root #{ selector-replace(&, &, "[#{$original}#{$child}]" ) } {
#content;
}
}
The code simply does the following
$string variable is responsible for turning the parent selector to a string using the inspect function
$original variable is responsible for getting the text content of the $string variable i.e the value 'data-parent' from '([data-parent])'
selector-replace function then replaces the parent selector with the concatenation of the $original variable and child variable
When used in the following ways
[data-parent] {
#include child-attribute('-child') {
color: green;
}
}
The css output
[data-parent-child] {
color: green;
}
Depending on what you want to achieve, it can also be used like this
[grandparent] {
#include child-attribute('-parent') {
color: white;
#include child-attribute('-child') {
color: blue;
}
}
}
Which generates the following css
[grandparent-parent] {
color: white;
}
[grandparent-parent-child] {
color: blue;
}
Hope this helps you
You can create mixin that will set styles for elements with data attribytes.
Scss:
#mixin data($name) {
[data-#{$name}] {
#content;
}
}
* {
#include data('lol') {
color: red;
};
}
Css output:
* [data-lol] {
color: red;
}
DEMO
I would go down a slightly different route of having a class on your elements that contain the data attributes.
<div class="data-obj" data-parent="true"></div>
<div class="data-obj" data-parent-child="true"></div>
then in your SASS do
.data-obj {
...
&[data-parent] { ... }
&[data-parent-child] { ... }
}

How can I create a Sass mixin with a class as a variable

I am trying to write something like this :
#mixin variableChild($child:".theChild") {
//some css
$child {
//css specific to the child
}
}
#parent { #include variableChild(".specificChild"); };
So it would generate this CSS :
#parent {//some css}
#parent .specificChild {
//css specific to the child
}
You were almost right, you just missed the #{} around your child selector I think. There’s more information about it in the Sass documentation.
#mixin variableChild($child:".theChild") {
#{$child} {
color: red;
}
}
#parent {
#include variableChild(".specificChild");
};
http://jsfiddle.net/UrLdB/

Resources