With the Sass extension Breakpoint, is there a preferred way to write vertical media queries that only have a single argument for the query value?
Here's an example of what I'd like to ultimately accomplish:
#media (max-height: 50em) {
.item {
font-size: 2em;
}
}
Or, should I just do a plain, "on-the-fly" media query for these styles like such:
.item {
#media (max-height: 50em) {
font-size: 2em;
}
}
Is this something that could possibly be handled with a variable?
My styles are "mobile first", so all of the other media queries on this site use Breakpoint's default "min-width" setting.
Thanks!
You can do the following:
$vertical: 'max-height' 50em;
.item {
#include breakpoint($vertical) {
font-size: 2em;
}
}
You can also include height queries with other queries as follows:
$mixed: 15em ('max-height' 50em);
.item {
#include breakpoint($mixed) {
font-size: 2em;
}
}
Related
I want to use one CSS style for two classes with mixin, but when I use mixin the final result will be 2 classes with the same CSS.
I have shared my code example below:
#mixin btnhover {
background-color: $bg-cl-blc;
color: $txt-cl-ff;
}
.btn-base {
font-size: 15px;
&:hover {
#include btnhover;
}
}
.btn-otln {
font-size: 15px;
&:hover {
#include btnhover;
}
}
**OUTPUT CSS**
.btn-base:hover {
background-color: #000;
color: #fff;
}
.btn-otln:hover {
background-color: #000;
color: #fff;
}
This is how Sass works - it allows for better organisation of the code, but this code is then compiled, retaining functionality and not caring about other aspects.
If you really care about how the output code is structured, I would suggest to create a separate style for the classes with the hover effect:
#mixin btnhover {
background-color: #000;
color: #fff;
}
.btn-base {
font-size: 15px;
}
.btn-otln {
font-size: 15px;
}
.btn-base:hover,
.btn-otln:hover {
#include btnhover;
}
But in this approach, the use of mixin (and Sass) is questionable (in this exact case).
Generally, when you use Sass (or any other compiled language), you don't really care about the output CSS.
This won't be your answer, but I want to show you another way to make a mixin
#mixin btnhover($back, $color) {
background: $back;
color: $color;
}
When you use it, you can plug in the values
#include mixin btnhover($bg-cl-blc, $txt-cl-ff)
That way you can use the mixin over and over in different places with different values
Just discovered this recently myself, it's a concept called 'placeholders' in SASS syntax (see example below). I've done my best to apply it to your situation below....
Put this in your .scss file:
$bg-cl-blc: #ff211a;
$txt-cl-ff: #fff;
$btn-base-size: 15px;
%btnhover {
background-color: $bg-cl-blc;
color: $txt-cl-ff;
}
%btn-common {
font-size: $btn-base-size;
}
.btn-base {
#extend %btn-common;
&:hover {
#extend %btnhover;
}
}
.btn-otln {
#extend %btn-common;
&:hover {
#extend %btnhover;
}
}
CSS output will look like this
.btn-otln:hover, .btn-base:hover {
background-color: #ff211a;
color: #fff;
}
.btn-otln, .btn-base {
font-size: 15px;
}
Great article written up on this here:
https://dev.to/kemotiadev/are-sass-mixins-really-that-lightweight-and-what-are-placeholders-119i
I migrated from stylus to sass. In stylus, you can use ^[N] for partial quoting. How to do this in sass?
The Stylus feature Partial Reference has no direct equivalent in SCSS/SASS.
In SASS the & always contains the complete parent selector and there is no feature to retrieve only a part of it.
There are however...
the special #at-root to ditch the parent and...
a combined technique to capture the parent selector in a local-scoped variable and to use string interpolation to create a selector from it.
See what it does:
.foo {
.bar { color: red; }
#at-root .bar { display: block; }
}
renders to:
.foo .bar { color: red; }
.bar { display: block; }
and
.foo {
$block-class: &;
&__header {
font-size: medium;
#at-root #{$block-class}.large-header & { font-size: large; }
}
&__footer {
color: red;
}
}
renders to:
.foo__header {
font-size: medium;
}
.foo.large-header .foo__header {
font-size: large;
}
.foo__footer {
color: red;
}
A word of caution: I would not recommend to use such elaborate SCSS gymnastics to impress and confuse anyone who ever needs to read your code. Really, just keep it simple. Sometimes it is the right thing to do to just repeat a selector in the code. No harm done.
Using Sass, I have the following mixin:
#mixin ss($property, $value, $value-smallscreen) {
#{$property}: $value;
#media screen and (max-height: $smallscreen-maxheight) {
#{$property}: $value-smallscreen;
}
}
.Header
{
#include ss('height', $RowHeight, $RowHeight-smallscreen);
#include ss('font-size', $HeaderFontsize, $HeaderFontsize-smallscreen);
}
The ‘problem’ that I have is that this generates two #media statements. That is, it generates the following CSS:
.Header {
height: 41px;
font-size: 11pt; }
#media screen and (max-height: 768px) {
.Header {
height: 35px; } }
#media screen and (max-height: 768px) {
.Header {
font-size: 9pt; } }
What I want to know, is there any way to both:
Keep the definitions together, to ensure that the styles are added for both big and small screens, and
Only have one '#media' section.
One of my current projects requires this approach to the SASS structure, and my solution has been to watch the CSS output using a CSS post-processor like Pleeease to watch the CSS files as SASS/Compass outputs them.
This allows live media query packing among other optimization.
I'm doing a code review for sass code and came across using media queries inside the code. Is it a good practice? Are there better alternatives to writing this code?
.col-md-push-8 {
padding-top: 1.5em;
.btn {
&.btn-block {
border: none;
background-color: $footer-button;
margin: 1em 0 .5em;
width: 100%;
padding: 7px 10px;
border-radius: 8px;
&:hover {
background-color: $footer-button-hover;
}
#media (min-width: $screen-md-min) {
color: #025191;
&:hover .media span p.media-heading {
color: #0070ca;
}
}
}
}
}
Note: The code is for illustration purpose only and is not completely shown here.
I think that what your way to do it is perfectly fine if you're using SASS >= 3.2 (was buggy before).
Just one thing that you could do to define your media queries breakpoints more globally is to create a mixin for that purpose that you will re-use on each element you need responsive.
This way when you have to change let's say your min breakpoint, add another or change your media min-width to max-width, you don't have to do it everywhere.
Some little example assuming you have already defined $screen-md-min and $screen-md-mid :
#mixin custom-media($size) {
#if ($size == $small) {
#media (min-width: $screen-md-min) { #content; }
}
#else if ($size == $middle) {
#media (min-width: $screen-md-mid) { #content; }
}
}
And call it like so :
.btn {
&.btn-block {
...
#include custom-media($small) {
color: #025191;
&:hover .media span p.media-heading {
color: #0070ca;
}
}
}
}
There is no difference if you put Media Query inside or outside. It just depends on your preffered style.
Style 1
.some-class {
#media (min-width: 700px) {
background: red;
}
}
Style 2
#media (min-width: 700px) {
.some-class {
background: red;
}
}
Both will compile as:
#media (min-width: 700px) {
.some-class {
background: red;
}
}
Sass handles this fine, but that code is going to produce overly qualified selectors and is hardly concise.
There are a number of patterns for writing “better” CSS and Sass, such as BEM, OOCSS, OOCSS + Sass, and SMACSS.
There's also a bunch of great information on Media Queries in Sass that is probably worth a read.
I have set up a mixin for a button using display:inline-block. I am trying to get to the parent of whatever class that will eventually end up using the mixim, so I can add the font-size: 0px line there to make sure that I don't need to make adjustments to my HTML to avoid unwanted space between each button.
Here's an example... I want the. parent class to receive the font-size: 0px line.
#mixin button() {
display:inline-block;
font-size: 1em;
//other stuff to make a pretty button
&& { font-size: 0px; }
}
.parent{
.child {
#include button();
}
}
As of Sass 3.4 this is now possible.
#mixin parent {
#each $selector in & {
$l: length($selector);
#if ($l == 1) {
#error "Used parent mixin on a top-level selector";
} #else {
$parent: nth($selector,1);
#for $i from 2 to $l {
$parent: append($parent,nth($selector,$i));
}
#at-root #{$parent} {
#content;
}
}
}
}
// Use
.grandparent {
.parent{
.child {
font-size: 1em;
#include parent {
font-size: 0px;
}
}
}
}
// Result
.grandparent .parent .child {
font-size: 1em;
}
.grandparent .parent {
font-size: 0px;
}
// Errors:
.root {
#include parent {
content: "Won't work";
}
}
.grandparent .parent, .root {
#include parent {
content: "Also won't work";
}
}
No, this is not possible. You could do something like this, though:
#mixin button($child: '.child') {
font-size: 0px;
//other stuff to make a pretty button
#{$child} {
display:inline-block;
font-size: 1em;
}
}
.parent{
#include button();
}
Output:
.parent {
font-size: 0px;
}
.parent .child {
display: inline-block;
font-size: 1em;
}
There is a XXX! selector in the draft for the CSS 4 spec, which will act as the way you like. It announces the subject of the CSS style declarations, if the selectors match
So if you have this selector
.a > .b! > .c
It will match e.g. for this
<div class="a">
<div class="b">
<div class="c">
</div>
</div>
</div>
but the style declarations will not take effect on .c, but on .b, because I announced by the exclamation mark, that this element should be the subject of the style
http://dev.w3.org/csswg/selectors4/#subject
You cannot use it right now out of the box. But there is one jQuery plugin, that is a polyfill for that. http://dev.w3.org/csswg/selectors4/
See also this stack: Is there a CSS parent selector?
How to apply?
Well, I don't know exactly in SASS, but in LESS it would be
*! > & {
/* ... */
}
While Karol's answer is near perfect, it doesn't take into account pseudo-elements or pseudo-selectors. Furthermore, code is duplicated if using more than one complex selector. I came up with a simplified version:
#mixin parent {
$parents: ();
$parent: '';
#each $selector in & {
$length: length($selector);
$index: 0;
$last-selector: nth($selector, $length);
#if ($length == 1) {
#error "Used parent mixin on a top-level selector";
} #else {
$index: str-index($last-selector, '::');
#if ($index) {
$last-selector: str-slice($last-selector, 1, $index - 1);
} #else {
$last-selector: null;
}
// Inspect allows us to combine two selectors in one block.
$parent: inspect(set-nth($selector, $length, #{$last-selector}));
$parents: join($parents, $parent, comma);
}
}
#at-root #{$parents} {
#content;
}
}
There's a first loop to iterate over the selector list (selectors with commas at the end). Because complex selectors are also treated as a list, we just need to remove the last element of the list. There's no loop to iterate over the compound or simple selectors since we only need to discard the last one.
There's no function in Sass to remove an element of a list, but we can set the value of an element with set-nth. By making the last element as an empty string and unquoting it, we can remove the last element from the printed representation (string) of the list. Since selectors can be strings, we simply use the new string as a selector.
When using the following:
.grandmother,
.grandfather {
.parent {
.child {
font-size: 10em;
#include parent {
font-size: 5em;
}
&::after {
font-size: 1px;
#include parent {
font-weight: bold;
}
}
}
}
}
We get the following:
.grandmother .parent .child,
.grandfather .parent .child {
font-size: 10em;
}
.grandmother .parent,
.grandfather .parent {
font-size: 5em;
}
.grandmother .parent .child::after,
.grandfather .parent .child::after {
font-size: 1px;
}
.grandmother .parent .child,
.grandfather .parent .child {
font-weight: bold;
}
Note: pseudo-elements and pseudo-selectors are not children of an element but are attached to it and have therefore no parents in themselves. I assumed parents would mean the parent in the sense of Sass nesting.