SASS - for h1-h6 style - css

I have SCSS style like this, I want to use #for from SCSS to write this more efficient.
So far:
#for $i from 1 through 6 {
h#{$i} {
$size: {$i} * 1.4;
#include font-size($size);
}
}
Note: don't mind calculation of size, its just for test
but syntax is not right.
Expected output
h1 {
#include font-size(3.2);
}
h2 {
#include font-size(2.4);
}
h3 {
#include font-size(1.8);
}
h4 {
#include font-size(1.6);
}
h5 {
#include font-size(1.3);
}
h6 {
#include font-size(1.2);
}

The main issue is your h1 increasing in size as it gets to a higher number (because you are using $i incrementally). You can escape that by reducing the h-number size using the formula 7 - $i.
#for $i from 1 through 6 {
h#{7 - $i} {
fontsize: $i * 1.4em;
}
}
The output here is:
h6 { font-size:1.4em }
h5 { font-size:2.8em }
h4 { font-size:4.2em }
h3 { font-size:5.6em }
h2 { font-size:7em }
h1 { font-size:8.4em }
Which seems to make sense. The original error you were getting was this:
Invalid CSS after "$size:": expected expression (e.g. 1px, bold), was "{$i} * 1.4;"
Because you can simply use $i as a number without special denotation.
To get the numbers to match with your question, you should actually find a way to calculate them on the fly - and the numbers you have shown above are not a pattern, so they are not mathematically controllable. Here's what you could do:
#for $i from 1 through 6 {
h#{7 - $i} {
fontsize: 3.4em / 6 * $i;
}
}
The reason this cannot be computed mathematically like your question desires is: h1 - h2 = .6em, h2 - h3 = .6em, h3 - h4 = .2em => That last one does not fall into line with any particular pattern.

Related

scss for loop is not cascading correctly

I have this for loop created like this:
.hero {
#for $i from 1 through 100 {
&.aspect-ratio--#{$i} {
#include aspect-ratio(16, $i);
}
&.aspect-ratio-sm--#{$i} {
#include media-breakpoint-up(sm) {
#include aspect-ratio(16, $i);
}
}
&.aspect-ratio-md--#{$i} {
#include media-breakpoint-up(md) {
#include aspect-ratio(16, $i);
}
}
&.aspect-ratio-lg--#{$i} {
#include media-breakpoint-up(lg) {
#include aspect-ratio(16, $i);
}
}
&.aspect-ratio-xl--#{$i} {
#include media-breakpoint-up(xl) {
#include aspect-ratio(16, $i);
}
}
}
}
When I create an element, like this:
<div class="hero aspect-ratio-md--6 aspect-ratio-sm--8 aspect-ratio--10"></div>
it's not respecting the order I declared my classes, so when I am in a md and above, instead of using aspect-ratio-md-6 it's actually using the aspect-ratio-10 instead.
like this:
Does anyone know what I am doing wrong?
Not sure why it voted down, but I figured this out.
It's because of how my loop was working, it was getting to 8 after 6, so that took precedence.
I changed my loop to this:
$breakpoints: sm, md, lg, xl, xxl;
.hero {
#each $breakpoint in $breakpoints {
#for $i from 1 through 100 {
&.aspect-ratio-#{$breakpoint}-#{$i} {
#include media-breakpoint-up($breakpoint) {
#include aspect-ratio(16, $i);
}
}
}
}
}
And this worked. Why? Because it looks through the breakpoints first meaning the last breakpoint will always take precedence over the first, then it loops from 1 to 100 and creates the classes, again, the later numbers taking precedence over the earlier numbers (not needed, but good to know)

How to get font size between two ranges in SCSS?

I want to get the font size between two ranges.
$base-font: 1px;
#for $i from 1 through 100 {
.th-#{i} {
font-size: $base-font + $i + px;
}
}
When I am using class .th-30, I am not getting a font size of 30px.
You can just remove the $base-font variable altogether. Also, you're missing a dollar sign in the selector:
#for $i from 1 through 100 {
.th-#{$i} {
font-size: $i + px;
}
}
Here's a working fiddle.
Here are some changes you need to do.
There is no need for $base-font here
$base-font: 1px;
#for $i from 1 through 100 {
.th-#{$i} {
font-size: #{$i}px;
}
}

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] { ... }
}

Using SASS's #for for multiple selectors and 1 body [duplicate]

I'm working with the SCSS syntax of SASS to create a dynamic grid system but I've hit a snag.
I'm trying to make the grid system completely dynamic like this:
$columns: 12;
then I create the columns like this:
#mixin col-x {
#for $i from 1 through $columns {
.col-#{$i} { width: $column-size * $i; }
}
}
Which outputs:
.col-1 {
width: 4.16667%;
}
.col-2 {
width: 8.33333%;
}
etc...
This works well but what I want to do next is dynamically generate a long list of column classes separated by commas based on the number of $columns chosen - e.g I want it to look like this:
.col-1,
.col-2,
.col-3,
.col-4,
etc... {
float: left;
}
I've tired this:
#mixin col-x-list {
#for $i from 1 through $columns - 1 {
.col-#{$i}-m { float: left; }
}
}
but the output is this:
.col-1 {
float: left;
}
.col-2 {
float: left;
}
etc...
I'm a little stuck on the logic here as well as the SCSS syntax required to create something like this.
Does anyone have any ideas?
I think you may want to take a look at #extend. If you set that up something like:
$columns: 12;
%float-styles {
float: left;
}
#mixin col-x-list {
#for $i from 1 through $columns {
.col-#{$i}-m { #extend %float-styles; }
}
}
#include col-x-list;
It should render in your css file as:
.col-1-m, .col-2-m, .col-3-m, .col-4-m, .col-5-m, .col-6-m, .col-7-m, .col-8-m, .col-9-m, .col-10-m, .col-11-m, .col-12-m {
float: left;
}
#extend in the docs.
There's also a way to do what your question is specifically asking for: generate (and use) a list of classes with commas separating them. D.Alexander's response totally works in your situation, but I'm posting this alternative in case there's another use case for someone looking at this question.
Here's a Pen demonstrating: http://codepen.io/davidtheclark/pen/cvrxq
Basically, you can use Sass functions to achieve what you want. Specifically, I'm using append to add classes to my list, separated by commas, and unquote to avoid compilation conflicts with the period in the classnames.
So my mixin ends up looking like this:
#mixin col-x {
$col-list: null;
#for $i from 1 through $columns {
.col-#{$i} {
width: $column-size * $i;
}
$col-list: append($col-list, unquote(".col-#{$i}"), comma);
}
#{$col-list} {
float: left;
}
}
thnx to #davidtheclark here is a more generic version:
#mixin attr-x($attr, $attr-count: 10, $attr-steps: 10, $unit: '%') {
$attr-list: null;
#for $i from 1 through $attr-count {
$attr-value: $attr-steps * $i;
.#{$attr}#{$attr-value} {
#{$attr}: #{$attr-value}#{$unit};
}
$attr-list: append($attr-list, unquote(".#{$attr}-#{$attr-value}"), comma);
}
#{$attr-list} {
//append style to all classes
}
}
Use it like this:
#include attr-x('margin-left', 6, 5, 'px');
//or
#include attr-x('width');
The result looks like this:
.margin-left5 {
margin-left: 5px; }
.margin-left10 {
margin-left: 10px; }
...
.margin-left30 {
margin-left: 30px; }
.width10 {
width: 10%; }
.width20 {
width: 20%; }
...
.width100 {
width: 100%; }

Sass and libraries for theming [duplicate]

I'm refactoring some of my Sass code and I came across a weird issue. My code currently looks like this:
// household
$household_Sector: 'household';
$household_BaseColor: #ffc933;
// sports
$sports_Sector: 'sports';
$sports_BaseColor: #f7633e;
// the mixin to output all sector specific css
#mixin sector-css($sector_Sector,$sector_BaseColor) {
.sector-#{$sector_Sector} {
&%baseColor {
background-color: $sector_BaseColor;
}
}
}
// execute the mixin for all sectors
#include sector-css($household_Sector, $household_BaseColor);
#include sector-css($sports_Sector, $sports_BaseColor);
.product-paging {
h2 {
#extend %baseColor;
}
}
DEMO
The compiled result looks like this:
.product-paging h2.sector-household {
background-color: #ffc933;
}
.product-paging h2.sector-sports {
background-color: #f7633e;
}
But what I need is this:
.sector-household.product-paging h2 {
background-color: #ffc933;
}
.sector-sports.product-paging h2 {
background-color: #f7633e;
}
What I don't understand is why my placeholder (&%baseColor) isn't attached to the parent selector (&%baseColor) as I added the ampersand right in front of it?
Is this maybe a bug when combining & and %? Is there another solution on how to achieve what I want?
EDIT
Alright I figured out why this isn't possible. Anyway is there a workaround for what I'd like to achieve?
Extends, as you've already discovered, can get rather messy. I would go about solving your problem by using an #content aware mixin in combination with global variables (this uses mappings, which are part of 3.3... you can do it with lists of lists, but it's a little less elegant):
$base-color: null; // don't touch
$accent-color: null; // don't touch
$sections:
( household:
( base-color: #ffc933
, accent-color: white
)
, sports:
( base-color: #f7633e
, accent-color: white
)
);
// the mixin to output all sector specific css
#mixin sector-css() {
#each $sector, $colors in $sections {
$base-color: map-get($colors, base-color) !global;
$accent-color: map-get($colors, accent-color) !global;
&.sector-#{$sector} {
#content;
}
}
}
.product-paging {
#include sector-css() {
h2 {
background-color: $base-color;
}
}
}
Output:
.product-paging.sector-household h2 {
background-color: #ffc933;
}
.product-paging.sector-sports h2 {
background-color: #f7633e;
}
Update: Since you want to guarantee that the sector class is always at the top, you just need to switch around a little.
#mixin sector-css() {
#each $sector, $colors in $sections {
$base-color: map-get($colors, base-color) !global;
$accent-color: map-get($colors, accent-color) !global;
.sector-#{$sector} {
#content;
}
}
}
#include sector-css() {
&.product-paging {
h2 {
background-color: $base-color;
}
h3 {
background-color: #CCC;
}
h2, h3 {
color: $accent-color;
}
}
}

Resources