sass dynamic width - sass

I'm using
.w400 {
width: 400px;
}
.w110 {
width: 110px;
}
.w600 {
width: 600px;
}
is it possible to make dynamic class with sass?
something like
.w(size) {
width: size+px
}

If you want to be able to use arbitrary .w(something) classes, I believe (see below) that is not possible with Sass. However, if you know beforehand what sizes you need, you could use mixins with arguments to generate the classes. Something like this:
#mixin width-class($size) {
.w#{$size} {
width: $size * 1px;
}
}
You would use it like this:
#include width-class(400);
#include width-class(110);
This generates the following CSS:
.w400 {
width: 400px; }
.w110 {
width: 110px; }
Now, if you want to avoid writing a new #include line for each of the classes, you can create another mixins (or combine the two mixins into one):
#mixin dynwidths($size-list) {
#each $size in $size-list {
#include width-class($size)
}
}
Now you can pass it a list of widths. This generates the same CSS as above:
#include width-classes(400 110);
Note: This is just a guess, but wildcard class names might be possible by extending Sass with Ruby. However, I'm not sure if this is a desirable feature.

Related

Inline scss variable as the name part in the evaluation of another scss variable

Suppose I have the following scss variables:
$until-xs: "(max-width: 377px)";
$until-sm: "(max-width: 640px)";
...
$until-xl: "(max-width: 4000px)";
And based on them the following helper css classes are constructed:
.until-sm {
display: none;
#media #{$until-xs} {
display: block !important;
}
}
.until-md {
display: none !important;
#media #{$until-sm} {
display: block !important;
}
}
/* plus a lot of classes like this */
I am trying to create a mixin that would help me define those classes more easily by passing the $until-x variable as an input to the mixin, like so:
#mixin until($x) {
display: none;
#media #{'$until-'#{$x}} {
display: block !important;
}
}
Such that the classes above will be defined simply as:
.until-xs { #include until($until-xs); }
The problem is the media variable inlining part does not evaluate the way I wanted, like:
#{'$until-'#{$x}} (when x is 'xs') =>
#{'$until-xs'} =>
#{$until-xs} =>
(max-width: 377px)
Any way I can achieve this? Since this can be applied in multiple places in my project I am more interested in the possibility of inlining vars like this than the solution to the particular problem from the example.
Instead of defining lots of variables like $until-xs, $until-sm and so on, you can define a map that contains information of your medias like the code below:
#use "sass:map";
$until-var: ("xs": "(max-width: 377px)", "sm": "(max-width: 620px)", "md": "(max-width: 807px)");
#mixin until($x) {
display: none;
#media #{map.get($until-var, $x)} {
display: block !important;
}
}
/* using that in your classes */
.until-xs { #include until("xs"); }
.until-sm { #include until("sm"); }
I'm not sure what you mean by inlining vars! But if you want a single mixin that works for different medias, I think that works.

Ampersand and mixins in SCSS

Searched but can't find an answer..
I have an element which gets generated (by an external platform) with the following classes: p-button and button.
Now the SCSS is like this:
.p-button {
&.button {
margin: 10px;
}
}
But I want to refactor using mixin includes (this is a big project so there is no other way of making this code better except using mixins). The mixin takes the given selector and applies a . to it. I can't change the mixin, as it is used by many other teams, so I can't pass the ampersand together with the selector. I tried this:
.p-button {
& {
#include button-appearance("button") {
margin: 10px;
}
}
}
But that doesn't work (puts a space between it). You can't do this:
.p-button {
&#include button-appearance("button") {
margin: 10px;
}
}
Anyone have a clue?
EDIT: Here is the mixin
#mixin button-appearance(
$appearance-class,
$show,
$background-color,
$background-image,
$background-position) {
$sel: $button-selector;
#if $appearance-class {
$sel: $sel + '.' + $appearance-class;
}
#{$sel} {
#include normalized-background-image($background-image);
#include show($show);
background-color: $background-color;
background-position: $background-position;
}
#content;
}
EDIT 2: Here is the $button-selector (I can not edit this in the platform, but maybe overwrite it in my own project?)
$button-class: 'p-button';
$button-selector: '.#{$button-class}';
Everyone, finally found the solution. I just removed the &.button from the .p-button mixin include and now it works:
#include button-appearance ("button") { *styles* }
#include button-appearance () { *styles* }
Edited the answer after the original question was edited adding the used and un modifiable mixin
The original mixin does not append the ‘#content’ passed to the mixin to the generated selector. So if you cannot modify the original mixin, the only way is to add your properties outside the mixin. According to the mixin the selector will match a predefined ‘$button-selector’ variable, so it won’t use your class.
So, if you want to use the same class defined in ‘$button-class’, try the following:
#{$button-selector}.button {
margin: 10px;
}
Will output:
.p-button.button {
margin: 10px;
}

#function v/s #mixin in Sass-lang. Which one to use?

After searching a lot in difference between #function and #mixin I ended up here.
Is there any advantage of using #mixin over #funcion or vice versa. In what context they'll be different, how to use them interchangeably, please come up with examples.
Functions are useful specifically because they return values. Mixins are nothing like functions--they usually just provide valuable blocks of code.
Usually, there are cases where you might have to use both.
For example, if I wanted to create a long-shadow with SASS, I would call a function like so:
#function makelongshadow($color) {
$val: 0px 0px $color;
#for $i from 1 through 200 {
$val: #{$val}, #{$i}px #{$i}px #{$color};
}
#return $val;
}
Which would then be called with this mixin:
#mixin longshadow($color) {
text-shadow: makelongshadow($color);
}
Which provides us with the actual code.
That gets included in the element:
h1 {
#include longshadow(darken($color, 5% ));
}
#function is useful when you want to reuse it on different CSS properties.
Example, You have dynamic values that you want to use on both height and min-height, then using #function is the one you would use:
#function dynamic-height($height, $padding) {
#return $height + $padding;
}
.foo {
min-height: dynamic-height(300px, 30px);
}
.bar {
height: dynamic-height(300px, 30px);
}
But if you want to reuse it with same CSS properties, then you would use a #mixin:
#mixin dynamic-height($height, $padding) {
min-height: $height;
padding: $padding;
}
.foo {
#include #dynamic-height(300px, 30px);
}
think of #mixin as it is just a #function that returns a block of style rules.
also, you can use placeholders (like %selector) and #extend

Can I set a Sass variable inside a breakpoint? [duplicate]

This question already has answers here:
Using Sass Variables with CSS3 Media Queries
(8 answers)
Closed 7 years ago.
Is it possible to set the value of a variable once, inside a single sass-breakpoint, rather than each time I use the variable?
In other words, I'd like to do this:
$tab: 600px;
$wp: 100%;
#include breakpoint($tab) {
$wp: 95%;
}
.alpha {
// ...
width: $wp;
}
.beta {
// ...
width: $wp;
}
.gamma {
// ...
width: $wp;
}
... rather than this:
$tab: 600px;
$wp: 100%;
$wp-tab: 95%;
.alpha {
// ...
width: $wp;
#include breakpoint($tab) {
width: $wp-tab;
}
}
.beta {
// ...
width: $wp;
#include breakpoint($tab) {
width: $wp-tab;
}
}
.gamma {
// ...
width: $wp;
#include breakpoint($tab) {
width: $wp-tab;
}
}
I don't think the first approach will work as is. Is there another way to achieve the same result? Is this approach a bad idea?
That is not possible.
Quoting nex3, the developer of Sass:
While this would be pretty cool, it's very much contrary to the
existing semantics of a Sass stylesheet. What you've outlined already
has a meaning: it sets the variable twice in sequence and then
accesses it (modulo some scoping issues). The sequential and largely
imperative nature of Sass means that the sort of automatic duplication
of rules you're describing becomes very complex. We actually
considered something very similar for handling SassScript &, and ended
up realizing that it was effectively impossible to do so and preserve
the existing semantics.
The best approximation you can do right now is to put the styles that
need to vary in a mixin with parameters and include that in your media
queries.
Source: https://github.com/nex3/sass/issues/1227

Abstract superclass

I'm trying to get SASS to do something akin to an abstract superclass in programming. I'm getting as far as the superclass part
.box {
#include span-columns(1);
#include border-radius(5px);
height: 360px;
overflow: hidden;
}
article {
#extend .box;
}
figure {
#extend .box;
}
This is a way to define commonalities of boxes without duplicating them in the generated CSS, as would happen with a mixin. However, this solution has the blemish of defining a rule for a (CSS) class "box" that I don't really need and want.
To be sure, this is a minor issue, still I'd like to know if there is a way to make ".box" into a label that is only used during SASS preprocessing and does not appear in CSS.
You want to define your "superclass" using a % instead of a .
%box {
#include span-columns(1);
#include border-radius(5px);
height: 360px;
overflow: hidden;
}
article {
#extend %box;
}
figure {
#extend %box;
}
Note that this requires version 3.2+

Resources