I have an Angular 9 app and when I use this snippet SCSS it returns this error:
SassError: Invalid parent selector "*"
╷
52 │ &#{$value} {
│ ^^^^^^^^^^^^^^^
╵
This is the snippet:
$values: (
"":"",
one: one,
two: two,
);
#mixin gen() {
#each $value, $key in $values {
#media (min-width: 300px) {
&#{$value} {
#content
}
}
}
}
#mixin display {
display: block;
}
.display > * {
#include gen() {
#include display();
}
}
I want in output classes for each value like: display > *, display-one > *, display-two > *and so on.
1. You want to select * after the value >, means you should add it in the mixin
2. You want select -#{$value} and not just &#{$value}. So A- you have to add the -, and B- for $value="" the - is not exist. so probably you should give it special attention.
Shortly, change the scss to
$values: (
one: one,
two: two,
);
#mixin gen() {
#media (min-width: 300px) {
> * {
#content
}
}
#each $value, $key in $values {
#media (min-width: 300px) {
&-#{$value} > * {
#content
}
}
}
}
#mixin display {
display: block;
}
.display {
#include gen() {
#include display();
}
}
Output:
#media (min-width: 300px) {
.display > * {
display: block;
}
}
#media (min-width: 300px) {
.display-one > * {
display: block;
}
}
#media (min-width: 300px) {
.display-two > * {
display: block;
}
}
What #Yosef describes is correct – however, there are a few things to consider
When using #each loops on maps the order is $key, $value.
To minimize the CSS output move the #each loop inside the media query – like:
#media (min-width: 300px) {
// move loop here
#each $key, $value in $values {
...
}
}
// CSS output without redundant media queries
#media (min-width: 300px) {
.display > * {
display: block;
}
.display-one > * {
display: block;
}
.display-two > * {
display: block;
}
}
Last but not least consider not doing this at all – use an attribute selector instead – this way you can handle everything in one selector :-)
#media (min-width: 300px) {
[class|=display] > * { display: block; }
}
// This will match
.display > *, .display-one > *, .display-two > *, .display-xxx > * etc.
Related
I'm trying to dynamically create a variable, but that doesn't seem to be possible in SCSS:
$res-mat-xs: 0;
$res-mat-sm: 600px;
$res-mat-md: 960px;
$res-mat-lg: 1280px;
$res-mat-xl: 1920px;
#mixin media-min($var) {
#media only screen and (min-width: $var) { #content; }
}
#mixin media-max($var) {
#media only screen and (max-width: $var - 1px) { #content; }
}
#mixin media-from-to($var1, $var2) {
#media only screen and (min-width: $var1) and (max-width: $var2 - 1px) { #content; }
}
$media: 'min', 'max', 'from-to';
$variants: 'very-small', 'small', 'default', 'large', 'very-large';
$breakpoints: 'xs', 'sm', 'md', 'lg', 'xl';
#each $breakpoint in $breakpoints {
.typo-style-#{$breakpoint}-#{$variants}-#{$breakpoint} {
#include media-min($res-mat-#{$breakpoint}) {
#include typo-style('default', 'important');
}
}
}
In addition, I am totally overwhelmed with the from-to ($media) and variants.
The class names for the from-to should look like this:
.typo-style-very-small-from-sm-to-md
.typo-style-large-from-sm-to-lg
How can I make these dynamic variables?
This my code: codesandbox.io
CSS
#media (width > 736px) {
#LogoMonni-mobile {
display: none;
}
}
#media (max-width <= 736px) {
#LogoMonni-pc {
display: none;
}
#LogoMonni-mobile {
display: block;
}
}
JSX
import { ReactComponent as LogoMonniPC } from "./logoMonniPC.svg";
import { ReactComponent as LogoMonniMobile } from "./LogoMonniMobile.svg";
import "./styles.css";
export default function App() {
return (
<div className={"LogoMonni"}>
<LogoMonniPC />
<LogoMonniMobile />
</div>
);
}
When the screen size is > 736px I show the computer version of the SVG, and when <= 736px I show the mobile version, but for some reason <LogoMonniMobile /> does not appear on the screen. What is the reason and how can this be fixed?
You cant use logical operators like <.
#media screen and (min-width: 737px) {
#LogoMonni-mobile {
display: none;
}
}
#media screen and (max-width: 736px) {
#LogoMonni-pc {
display: none;
}
#LogoMonni-mobile {
display: block;
}
}
As i understand the id problem LogoMonni_0 LogoMonni_1 LogoMonni_2 ... if id sv1 are the same as scg2 I don’t know for some reason the browser thinks they should disappear
Here's my code:
$responsive-adjust-amounts: (
2.5, //phone
2, //tablet
1.5, //laptop
1.25 //desktop
);
$responsive-devices: ("#{$phone}", "#{$tablet}", "#{$laptop}", "#{$desktop}");
#each $device in $responsive-devices {
#media #{$device} {
#for $i from 1 through length($responsive-adjust-amounts) {
#media #{$device} {
#{nth($responsive-adjust-amounts, $i)} {
#include font-adjustments(nth($responsive-adjust-amounts, $i));
}
}
$i: $i + 1;
}
}
}
Ultimately, I'm wanting it to create this end result:
#media #{$phone} {
#include font-adjustments(nth($responsive-adjust-amounts, 1));
}
#media #{$tablet} {
#include font-adjustments(nth($responsive-adjust-amounts, 2));
}
#media #{$laptop} {
#include font-adjustments(nth($responsive-adjust-amounts, 3));
}
#media #{$desktop} {
#include font-adjustments(nth($responsive-adjust-amounts, 4));
}
Could anyone provide any assistance where I'm getting stuck? Thank you in advance!
Excitedly, I've solved my own problem just now. Here's how:
#each $device in $responsive-devices {
$i: index($responsive-devices, #{$device});
#media #{$device} {
#include font-adjustments(nth($responsive-adjust-amounts, $i))
}
}
Additionally, I forgot to include the font-adjustments mixin in the original post. So here is that for anyone's review if needed in the future:
#mixin font-adjustments($amount) {
body {font-size: ($body-base * $amount)}
h4 {font-size: ($subhead-base * $amount)}
h1 {font-size: ($h1-base * $amount)}
}
I want to generate media queries grids having the below format:
I use a first large/desktop approach, with floats. It is intentional used instead of mobile-first approach.
#media (max-width: 36em) {
.col-1#sm {
width: 25%; }
.col-2#sm {
width: 50%; }
.col-3#sm {
width: 75%; }
.col-4#sm {
width: 100%; }
}
starting from the following grid-config map:
$grid-config: (
lg: (
width: em(960px),
columns: 16,
gutter-horizontal: rem(8px)
),
md: (
width: em(768px),
columns: 8,
gutter-horizontal: rem(8px)
),
sm: (
width: em(568px),
columns: 4,
gutter-horizontal: rem(8px)
),
);
For the first element in the map(lg) I don't want to add a media query.
The first element can change, so I don't want to do a string check (if bp !=='lg') if possible(not like in my code)
I have the following mixin to generate media-query:
#mixin media-breakpoint($bp) {
$columns: get-grid($bp, columns) !global;
#if $bp != 'lg2' {
#media (max-width: get-grid($bp, width)) {
#content
}
} #else {
#content
}
}
and another mixin to generate grid:
#mixin grid-generator {
#each $key, $value in $grid-config {
$bp: $key !global;
&--#{$key} {
#content;
}
}
}
Then I use:
.col {
#include grid-generator {
#include media-breakpoint($bp) {
$grid-columns: get-grid($bp, 'columns');
#for $i from 1 through $grid-columns {
&-#{$i} {
width: 100%/$grid-columns * $i;
}
}
}
}
}
but this generates the following format col--sm-1 and not col-1#sm.
The problems I have:
keep the cols inside media queryset, and add the media at the end.
compare to first in grid-config dynamic, check if $bp == first in map, instead of lg
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%; }