I have a simple SASS code that may be working like when the user has on his device set preferred color scheme dark the parameters from %dark-theme will extend to <body> and also when the user has preferred color scheme light the %light-theme will be extended instead of %dark-theme to <body>.
The same parameters which are used in %dark-theme and %light-theme may be extended on <body> when <body> have set id to #switched-dark-mode or #switched-light-mode. This IDs are set by Javascript after user switch the theme color.
Is there any solution to how I can make my SCSS clear and parameters which are used in #extends write only one time and use them in media query and also in ID selector?
MY CODE:
%dark-theme {
background: black;
color: white;
}
%light-theme {
background: white;
color: black;
}
#media (prefers-color-scheme: dark) {
body {
#extend %dark-theme;
}
}
#media (prefers-color-scheme: light) {
body {
#extend %light-theme;
}
}
body {
&#switched-dark-mode {
#extend %dark-theme;
}
&#switched-light-mode {
#extend %light-theme;
}
}
Unfortunately you cannot specify multiple selectors when using #media queries in SCSS (or at least to my knowledge). What you have already is a good solution.
One workaround you could try would be to use the "prefers-color-scheme" query in JavaScript when you load the page to apply the appropriate ID on the body element, which would allow you to remove the two #media queries from your SCSS code.
That means you could just move the styles defined in %dark-theme and %light-theme into the appropriate body selector.
Check out this post for reference and other solutions:
How to override css prefers-color-scheme setting
Related
I need to apply some styles to a div for printing. I can use a media query #media print {} to accomplish this easily. But I also sometimes need to apply the same styles on the browser itself, before the print dialog is opened. I'm trying to do this by adding a div .print-view to the page. But can't find a way to do it without code duplication.
I've tried this, but it's invalid css:
.print-view, #media print {
.grey-background {
background-color: white;
}
}
I've also tried this (scss), but it causes an error #extend may only be used within style rules.
.print-view {
.grey-background {
background-color: white;
}
}
#media print {
#extend .print-view;
}
Is there some other way for me to accomplish this?
Edit: changed sample code to more accurately reflect what I'm trying to do
Found the answer here. #include can be used to add a mixin into both a media query and a normal selector.
#mixin print {
.grey-background {
background-color: white;
}
}
.print-view {
#include print;
}
#media print {
#include print;
}
This compiles to the following css:
.print-view .grey-background {
background-color: white;
}
#media print {
.grey-background {
background-color: white;
}
}
I use Sass and I want to apply some style with two conditions
first if media query < desktop
second if the container have class "affiliations"
How can I wrote it without duplicate the style
I try the following but its not work
#include media ('<desktop'),.affiliations {
.search
{
color:red;
.icon{
color: blue;
}.........etc
}
}
What you are trying to do can't be done with only sass, usually you would structure your code like this
.someclass {
color: deepskyblue;
#media (max-width: 1023) {
.affiliations & {
color: deeppink;
}
}
}
I have a design where I need to be able to change colours on a page depending on the input in the cms.
To do this I'm adding one class to a containing div and I'll change the colours according to that surrounding class.
There's going to be a set amount of colours. (8, I think. It's not been decided yet.)
My idea was to use a mixin to accomplish this. eg.
Example HTML
<div class="color-1>
<h1 class="h1">My Title</h1>
</div>
Example LESS Mixin
.color() {
#color_1: red;
.color-1 & {
color: #color_1;
}
#color_2: blue;
.color-2 & {
color: #color_2;
}
//etc.....
//I have a similar mixin for background-color -> .bg-color();
}
Example LESS
.h1 {
.color();
background-color: #fff;
#media screen and (min-width: 960px) {
color: #fff;
.bg-color();
}
}
Problem
The problem is that the specificity for the mobile version is higher than the desktop one.
Example rendered CSS
//Could be color-2, color-3 etc. depending on class, doesn't matter for this example
.color-1 .h1 { //This would override the media query below due to 2 classes
color:red;
}
.h1 {
#media screen and (min-width: 960px) {
color: #fff;
background:color: red;
}
}
This issue will effect the rest of the page. Is there a better way to accomplish what I'm looking for without sticking important tags everywhere?
________________Edit________________
For clarity, the site I'm building will allow logged in users of a certain tier to change the main colour of their personal page, I still need the client to decide on how many colours but I think it will be around 8. Instead of writing out each of those, or having a separate stylesheet for each one (Maintaining that would be horrible) I decided to create a Mixin for it. There will be mutiple background colours and text colours that need to change, and due to the design they will need the change to different colours at mobile desktop and tablet.
Thinking of the nature of CSS something must be amiss with your code as the browser will always take the last value you give to a certain selector.
For example the following h1 would be red:
<h1 class="foo">Headline</h1>
.foo { color: blue; }
.foo { color: red; }
And it will change it's color when you give it a different value inside a mediaquery if the mediaquery is matched. So in the example below the h1 will be green when the viewport exceeds 399px in width:
<h1 class="foo">Headline</h1>
.foo { color: blue; }
.foo { color: red; }
#media all and (min-width: 400px) {
.foo { color: green; }
}
What's confusing me is the difference between your LESS code and what's in the outpout CSS. I'd suggest you have a second look at your selectors and/or variables. Indentation can be quite confusing as well, so may be you should opt for a mobile-first LESS file and then create others for mediaqueries (and import those in a main less file keeping the order intact).
Is there some type of value that can be assigned any arbitrary string using CSS? For example, "large" or "small".
My purpose is to watch a generic div with display: none and change this as-of-yet-unknown type of value "large" or "small" via a media query. Javascript will watch for this change and use the assigned value.
Example HTML:
<div class="state"/>
Example corresponding SASS:
.state {
#media #{$isSmall} {
unknown-type-of-value: "small";
}
#media #{$isLarge} {
unknown-type-of-value: "large";
}
}
You can't change the value of a <div> with CSS, but you can use :after to have css "append" text to it.
Something like
#media screen{
div.test:after{
content: "small";
}
}
#media print{
div.test:after{
content: "large";
}
}
DEMO: http://jsbin.com/edirad/1 (try to print it, and look at the preview)
I have an item class and a compact "modifier" class:
.item { ... }
.item.compact { /* styles to make .item smaller */ }
This is fine. However, I'd like to add a #media query that forces the .item class to be compact when the screen is small enough.
On first thought, this is what I tried to do:
.item { ... }
.item.compact { ... }
#media (max-width: 600px) {
.item { #extend .item.compact; }
}
But this generates the following error:
You may not #extend an outer selector from within #media. You may only
#extend selectors within the same directive.
How would I accomplish this using SASS without having to resort to copy/pasting styles?
The simple answer is: you can't because Sass can't (or won't) compose the selector for it. You can't be inside of a media query and extend something that's outside of a media query. It certainly would be nice if it would simply take a copy of it instead of trying to compose the selectors. But it doesn't so you can't.
Use a mixin
If you have a case where you're going to be reusing a block of code inside and outside of media queries and still want it to be able to extend it, then write both a mixin and an extend class:
#mixin foo {
// do stuff
}
%foo {
#include foo;
}
// usage
.foo {
#extend %foo;
}
#media (min-width: 30em) {
.bar {
#include foo;
}
}
Extend the selector within a media query from the outside
This won't really help your use case, but it is another option:
%foo {
#media (min-width: 20em) {
color: red;
}
}
#media (min-width: 30em) {
%bar {
background: yellow;
}
}
// usage
.foo {
#extend %foo;
}
.bar {
#extend %bar;
}
Wait until Sass lifts this restriction (or patch it yourself)
There are a number of ongoing discussions regarding this issue (please don't contribute to these threads unless you have something meaningful to add: the maintainers are already aware that users desire this functionality, it's just a question of how to implement it and what the syntax should be).
https://github.com/sass/sass/issues/1050
https://github.com/sass/sass/issues/456
For the record, here is how I ended up solving the problem with only duplicating generated styles once:
// This is where the actual compact styles live
#mixin compact-mixin { /* ... */ }
// Include the compact mixin for items that are always compact
.item.compact { #include compact-mixin; }
// Here's the tricky part, due to how SASS handles extending
.item { ... }
// The following needs to be declared AFTER .item, else it'll
// be overridden by .item's NORMAL styles.
#media (max-width: 600px) {
%compact { #include compact-mixin; }
// Afterwards we can extend and
// customize different item compact styles
.item {
#extend %compact;
/* Other styles that override %compact */
}
// As shown below, we can extend the compact styles as many
// times as we want without needing to re-extend
// the compact mixin, thus avoiding generating duplicate css
.item-alt {
#extend %compact;
}
}
I believe SASS/SCSS does not support the #extend directive inside of a media query. http://designshack.net/articles/css/sass-and-media-queries-what-you-can-and-cant-do/
You might need to use a mixin instead, though the code bloat needs to be weighed against your objective.
This is the cleanest, partial solution I've found. It takes advantage of #extend where possible and falls back to mixins when inside media queries.
Cross-Media Query #extend Directives in Sass
See the article for full details but the gist is that you call a mixin 'placeholder' that then decides whether to output #extend or an #include.
#include placeholder('clear') {
clear: both;
overflow: hidden;
}
.a {
#include _(clear);
}
.b {
#include _(clear);
}
.c {
#include breakpoint(medium) {
#include _(clear);
}
}
Ultimately it may not be better than just using mixins, which is currently the accepted answer.
I use breakpoints, but it's the same idea:
#mixin bp-small {
#media only screen and (max-width: 30em) {
#content;
}
How to use it:
.sidebar {
width: 60%;
float: left;
#include bp-small {
width: 100%;
float: none;
}
}
There is a text about mixins where you can find out more about this option.
Could you restructure?
.compact { //compact-styles }
.item {}
.item.compact { #extend .compact }
#media (max-width: 600px) {
.item { #extend .compact; }
}
If I understand the documentation correctly, that should work. I think the reason the way you're trying won't work is that it doesn't see .item.compact when it's parsing the #extend, but that's an uninformed guess, so take that with a truck load of salt! :)