I'm trying to think of a simple way to invert the darken/lighten color function using a variable. Something like so...
$invert_switch: off;
And...
#if $invert_switch == "on" {
darken == lighten
lighten == darken
} #else {
darken == darken
lighten == lighten
}
I know that's not proper code, I'm just trying to explain it very simply.
If this was used...
background: darken($bg, 10%);
color: lighten($txt, 50%);
How could I flip that, so it would be...
background: lighten($bg, 10%);
color: darken($txt, 50%);
Or maybe there is an easier way?
I try to change the name of the functions darken and lighten but I can't. The problem I have found is that SASS haven't something like #break or #continue to exit for the function and do nothing, my idea was the following code but when the custom fuction coincides with the SASS function goes to a infinite loop:
$invert_switch: on;
#function darken($color, $amount){
#if $invert_switch == on {
#return lighten($color, $amount);
}
#else {
#return darken($color, $amount);
}
}
#function lighten($color, $amount){
#if $invert_switch == on {
#return darken($color, $amount);
}
#else {
#return lighten($color, $amount);
}
}
h1{
color: darken(red, 10%);
}
p{
color: lighten(red, 10%);
}
I change the name of the functions adding a underscore to work:
$invert_switch: on;
#function _darken($color, $amount){
#if $invert_switch == on {
#return lighten($color, $amount);
}
#else {
#return darken($color, $amount);
}
}
#function _lighten($color, $amount){
#if $invert_switch == on {
#return darken($color, $amount);
}
#else {
#return lighten($color, $amount);
}
}
h1{
color: _darken(red, 10%);
}
p{
color: _lighten(red, 10%);
}
Maybe someone can improve this code using the proper names of functions
Related
How could you convert this function written in SASS to LESS? It converts pixelvalues to rem.
#function unit($number) {
#return $number / ($number * 0 + 1);
}
#function getRems($Pixels, $_base-fontsize:16px) {
$getRems: ();
#each $pixel in $Pixels {
$getRems: append($getRems, strip-unit($pixel) / strip-unit($_base-
fontsize) + rem,'space');
}
#return $getRems;
}
.image {
padding:getRems(250px 25px 10px 50px);
}
I have a mixin that converts px to rem PX TO REM, I have this code:
.button {
#include rem(font-size, 24px);
#include rem(padding, 10px);
#include rem(border-radius, 5px);
}
This would produce this CSS:
.button {
font-size: 1.5rem;
padding: 0.625rem;
border-radius: 0.3125rem; }
But I'd like to use some mixins from compass and for example I want to use border-radius from compass
.box {
#include border-radius(10px);
}
And it would generate this CSS:
.box {
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px; }
Is there a way to do something like this:
.box {
#include rem(#include border-radius(10));
}
You can't add two mixins together the way you'd like. So you just have to make the rem mixin do what you want it to do. So I wrote new code to handle that for you.
#function parseInt($n) {
#return $n / ($n * 0 + 1);
}
#mixin rem($property, $values, $prefix: false) {
$px: ();
$rem: ();
#each $value in $values {
#if $value == 0 or $value == auto or unit($value) == "%" {
$px: append($px, $value);
$rem: append($rem, $value);
} #else {
$unit: unit($value);
$val: parseInt($value);
#if $unit == "px" {
$px: append($px, $value);
$rem: append($rem, ($val / 16 + rem));
}
#if $unit == "rem" {
$px: append($px, ($val * 16 + px));
$rem: append($rem, $value);
}
}
}
#if $px == $rem {
#{$property}: $px;
} #else if $prefix == true {
#{-moz- + $property}: $px;
#{-moz- +$property}: $rem;
#{-webkit- +$property}: $px;
#{-webkit- +$property}: $rem;
#{$property}: $px;
#{$property}: $rem;
} #else {
#{$property}: $px;
#{$property}: $rem;
}
}
Now all you have to do add prefixes to any property is add the value true to the end of the mixin like so...
#include rem(border-radius, 10px, true);
Otherwise if you don't want any prefixs on property like fon-size or something you just don't add a last value like so...
#include rem(font-size, 10px);
I have a working demo here...
*Also on a side note I modified this mixin to handle percentages too.
I'm trying to style placeholders for input fields (for different browsers) in Sass 3.3.1, and want to change the opacity when the field is focused. I'm having a hard time combining the pseudo-class and pseudo-elements with the ampersand. The following gives a compilation error:
::-webkit-input-placeholder,
:-moz-placeholder,
::-moz-placeholder,
:-ms-input-placeholder{
... some default styling
:focus#{&}{
opacity: 0;
}
}
Can this be done?
Edit
This is the output I am looking for:
::-webkit-input-placeholder {
opacity: 1;
}
:-moz-placeholder{
opacity: 1;
}
::-moz-placeholder{
opacity: 1;
}
:-ms-input-placeholder{
opacity: 1;
}
:focus::-webkit-input-placeholder {
opacity: 0;
}
:focus:-moz-placeholder{
opacity: 0;
}
:focus::-moz-placeholder{
opacity: 0;
}
:focus:-ms-input-placeholder{
opacity: 0;
}
// Cross-browsers opacity: #include opacity(0.5);
#mixin opacity($opacity) {
opacity: $opacity;
$opacity-ie: $opacity * 100;
filter: alpha(opacity=$opacity-ie); //IE8
}
// Transitions for all: #include transition($transition);
$transition: all .3s ease;
#mixin transition($value) {
-webkit-transition: $value;
-moz-transition: $value;
-ms-transition: $value;
-o-transition: $value;
transition: $value;
}
// Input placeholder animation: #include placeholder { color: #000 }
#mixin placeholder {
&::-webkit-input-placeholder {
#content;
}
&:-moz-placeholder {
#content;
}
&::-moz-placeholder {
#content;
}
&:-ms-input-placeholder {
#content;
}
}
// How to use:
input {
text-overflow: ellipsis;
color: mediumseagreen;
#include placeholder {
color: cornflowerblue;
transition: $transition;
#include opacity(1);
}
&:focus {
#include placeholder {
#include opacity(0);
transition: $transition;
}
}
}
This is going to be the other way around, actually:
element:focus{
&::-webkit-input-placeholder,
&:-moz-placeholder,
&::-moz-placeholder,
&:-ms-input-placeholder{
opacity: 0;
}
}
Edit
I seem to have a problem combining them in my testing, but the following should work:
::-webkit-input-placeholder{
color: red;
&:focus{
color: blue;
}
}
On thing to note, though, is that this only works if they are separated out. You cannot combine multiple pseudo-selectors to one definition (like ::-webkit-input-placeholder, :-moz-input-placeholder{ /* this does not work in my testing */ }).
Update 2
Heres a quick SASS function I mocked up that will simplify the process:
#mixin input-placeholder($all:default){
#if $all == default {
$all : ("::-webkit-input-placeholder", ":-moz-placeholder","::-moz-placeholder",":-ms-input-placeholder");
}
#each $placeholder in $all {
#{unquote($placeholder)}{
#content;
}
}
}
You can use it by doing the following:
#include input-placeholder{
color: red;
&:focus {
color: blue;
}
}
This means you only have to write your code once. It will output all of them on individual lines and apply the same rules to them.
Solution from SASS Compass:
// Style the html5 input placeholder in browsers that support it.
//
// The styles for the input placeholder are passed as mixin content
// and the selector comes from the mixin's context.
//
// For example:
//
// #{elements-of-type(text-input)} {
// #include input-placeholder {
// color: #bfbfbf;
// font-style: italic;
// }
// }
//
// if you want to apply the placeholder styles to all elements supporting
// the `input-placeholder` pseudo class (beware of performance impacts):
//
// * {
// #include input-placeholder {
// color: #bfbfbf;
// font-style: italic;
// }
// }
#mixin input-placeholder {
#include with-each-prefix(css-placeholder, $input-placeholder-support-threshold) {
#if $current-prefix == -webkit {
&::-webkit-input-placeholder { #content; }
}
#elseif $current-prefix == -moz {
// for Firefox 19 and below
#if support-legacy-browser("firefox", "4", "19", $threshold: $input-placeholder-support-threshold) {
&:-moz-placeholder { #content; }
}
// for Firefox 20 and above
&::-moz-placeholder { #content; }
}
#elseif $current-prefix == -ms {
&:-ms-input-placeholder { #content; }
}
}
// This is not standardized yet so no official selector is generated.
}
So I'm trying to pass a modifier into a SASS mixin:
$headerHeight: 40px;
#mixin hh($prop, $mod: " + 0") {
#{$prop}: #{$headerHeight + $mod};
}
.something {
#include hh(padding-top, " * 2"); // Should return padding-top: 80px;
}
I keep getting things like padding-top: 40px + 0; no matter how many times I try and unquote it. Is it not possible to have the math string evaluated inside a mixin?
I've tried it without the px on $headerHeight, but that doesn't seem to work either.
I can do something like this:
#mixin hh($prop, $aMod: 0px, $mMod: 1) {
#{$prop}: ($headerHeight + $aMod) * $mMod;
}
But I'd prefer to just be able to put any arbitrary math string in there instead of having to break up the additive and multiplicative aspects of the math.
Thanks
Unfortunately, you would have to do something like create functions that act as operators for you and call them with the call() function inside your mixin:
#function plus($i, $j: 0) {
#return $i + $j;
}
#function times($i, $j: 0) {
#return $i * $j;
}
$headerHeight: 40px;
#mixin hh($prop, $func, $mod) {
#{$prop}: call($func, $headerHeight, $mod);
}
.something {
#include hh(padding-top, 'plus', 2); // 42px
#include hh(padding-bottom, 'times', 2); // 80px
}
I don't think that this is possible, you could do something like the following however to achieve the same goal:
$headerHeight: 40;
#mixin hh($prop, $mod, $modval) {
#if $mod == '+' {
#{$prop}: $headerHeight + $modval * 1px;
}
#if $mod == '-' {
#{$prop}: $headerHeight - $modval * 1px;
}
#if $mod == '*' {
#{$prop}: $headerHeight * $modval * 1px;
}
#if $mod == '/' {
#{$prop}: $headerHeight / $modval * 1px;
}
}
.something {
#include hh(padding-top, '*', 2); // Should return padding-top: 80px;
}
http://sassmeister.com/gist/be55fe73c307d0ad018c
I'm trying to loop through a list of values in Sass and use interpolation of the current key to dynamically output class names that utilize #include and #extend, respectively.
Here is a pen showing the problem, simplified. http://codepen.io/ghepting/pen/vBmLy
As you can see in the markup, I have tried including the "_" inside of the interpolated string as well as outside of it. Is there something I'm missing to work around this limitation of how Sass supports interpolation?
(Note: the OP's pen has disappeared. This is not the original code found in the pen, but a rough approximation of the problem)
$error-light: red;
$error-dark: darken(red, 10%);
$success-light: green;
$success-dark: darken(green, 10%);
$dialogs: error, success;
#each $d in $dialogs {
.#{$d} {
background: $#{$d}-light;
}
}
Interpolation doesn't work on mixins or variables at this point in time. You'll have to come up with a different way to achieve your goal.
As of Sass 3.3, you can use mappings for this purpose for variables:
$dialogs:
( error:
( light: red
, dark: darken(red, 10%)
)
, success:
( light: green
, dark: darken(green, 10%)
)
);
#each $name, $colors in $dialogs {
.#{$name} {
color: map-get($colors, dark);
}
}
And for functions:
#function green() {
#return lighten(green, 10%);
}
#function red() {
#return lighten(red, 10%);
}
#mixin my-bg($function-name) {
background: call($function-name);
}
.foo {
#include my-bg('red');
}
Alternative workaround (for a particular use case):
https://sass-lang.com/documentation/at-rules/mixin#passing-arbitrary-arguments
💡 Fun fact:
Because an argument list keeps track of both positional and keyword arguments, you use it to pass both at once to another mixin. That makes it super easy to define an alias for a mixin!
If you are interested in mixin interpolation because you have a group of mixins, like this:
//_mixins.scss
#mixin text-style-1($args...){ //sass here }
#mixin text-style-2($args...){ //sass here }
#mixin text-style-3($args...){ //sass here }
//_text.scss
.text-style-1 {
#include text-style-1;
}
.text-style-1-contrast {
#include text-style-1($contrast: true);
}
.text-style-2 {
#include text-style-2;
}
.text-style-2-contrast {
#include text-style-2($contrast: true);
}
We can take advantage of passing arbitrary arguments and use an alias for the group:
//_mixins.scss
#mixin text-style-1($args...){ //sass here }
#mixin text-style-2($args...){ //sass here }
#mixin text-style-3($args...){ //sass here }
#mixin text($mixin, $args...) {
#if $mixin == 'style-1' { #include text-style-1($args...); }
#else if $mixin == 'style-2' { #include text-style-2($args...); }
#else if $mixin == 'style-3' { #include text-style-3($args...); }
}
//_text.scss
$text-styles: 'style-1', 'style-2', 'style-3';
#each $style in $text-styles {
.text-#{$style} {
#include text($style);
}
.text-#{$style}-contrast {
#include text($style, $contrast: true);
}
}
Ran into this issue of trying to include an interpolated variable inside a mixin and was able to resolve it with placeholders:
%color-scheme-dark-bg-1 { background-color: #4e5163; }
%color-scheme-dark-color-1 { color: #4e5163 !important; }
%color-scheme-light-bg-1 { background-color: #c7c8ce; }
%color-scheme-dark-bg-2 { background-color: #fd6839; }
%color-scheme-dark-color-2 { color: #fd6839 !important; }
%color-scheme-light-bg-2 { background-color: #fecfc1; }
.card_color {
#mixin CardColorScheme($arg: 1) {
.borderPercent {
#extend %color-scheme-dark-bg-#{$arg};
}
.border {
#extend %color-scheme-light-bg-#{$arg};
}
ul li:before {
#extend %color-scheme-dark-color-#{$arg};
}
.percent {
#extend %color-scheme-dark-color-#{$arg};
}
.heading {
#extend %color-scheme-dark-color-#{$arg};
}
}
&--scheme {
&-1 {
#include CardColorScheme(1);
}
&-2 {
#include CardColorScheme(2);
}
}
}
Hat tip to: https://krasimirtsonev.com/blog/article/SASS-interpolation-in-a-name-of-variable-nest-variables-within-variables