Can I use a sass extend into a mixin? - sass

I wanna use an extend into a sass mixin
I have created an extend name flex then I use it into the centering item mixin. can I use it like?
//making a extend
%flex{
display:flex;
flex-wrap:wrap;
}
//mixin for centering an item
#mixin center-item(){
#include %flex;
justify-content:center;
align-items:center;
}

Yes. As long as the #mixin is included within a selector and #extend is used instead of #include to extend the silent-class, opposing to your example.
%example {
example: example;
}
#mixin example() {
#extend %example;
}
.example {
#include example();
}

Related

How to prefix SASS blocks with a specific scope ID via mixin

Looking to be able to add the app scope id to my sass files when we have multiple apps reusing class names.
That way I can have the following definition:
$app-scope-id: 'appOne';
And then write my SCSS in that app
.blockName{
background: blue;
&__element{
color: orange;
}
}
And call a mixin or something else to just go
#include prefixMixin(){
.blockName{
background: blue;
&__element{
color: orange;
}
}
}
And that render out css like:
.appOne-blockName{ background: blue; }
.appOne-blockName__element{ color: orange }
I'm aware I can use interpolation at the beginning of my block, but was hoping I could keep it cleaner with just a mixin call where necessary and only call it once for an entire SASS file if I wanted.
I don't think it's possible to do what you want with SASS. You could maybe do something like this:
$app-scope-id: 'appOne';
#mixin prefix($selectorType: ".") {
#at-root {
#{$selectorType}#{$app-scope-id}-#{&} {
#content;
}
}
}
blockName {
#include prefix() {
background: blue;
&__element{
color: orange;
}
}
}
Which compiles as:
.appOne-blockName { background: blue; }
.appOne-blockName__element { color: orange; }
But you would still need to include it for each selector that needs the prefix. I'm not sure this can be called "clean" either.

SCSS How to change order of rendering included mixins

This is a hard question, so I am aware that no one may come up with solution, but that's the problem I really need to solve in my framework.
I have a screen() mixin written in SCSS, which takes $size as an argument, to return any #content wrapped in a media query.
The problem occurs when one element #includes multiple screen() mixins, because resulting media queries will overwrite each other in the same order as they were included. How can I make sure the resulting media queries will be rendered in the correct order (biggest screen to smallest), even if I forget to include them in the right order?
http://sassmeister.com/gist/951520fa83d1e1c69c9d
#mixin screen(
$size: null
){
#if $size == md {
#media (max-width: 1024px) {
#content;
}
}
#if $size == sm {
#media (max-width: 768px) {
#content;
}
}
#if $size == xs {
#media (max-width: 320px) {
#content;
}
}
}
/* output should be 1024, 768, 320 */
.screen {
&:before {
// this should be included as the Last one
#include screen(xs){
content: "xs";
}
#include screen(sm){
content: "sm";
}
// this should be included as the First one
#include screen(md){
content: "md";
}
}
}
I tried to solve that issue by creating placeholder selectors in the right order %media-sm{...}, %media-xs {...}..., and #extend them from the mixin, but #content can't be passed through the #extend directive.
Another solution is a hard one - create an array of keys - sizes, and values - #contents and render them from another function.
No. Sass only does exactly what you tell it to do. If you want your styles to appear in a specific order, write them in that specific order.
Might be easier to pass in the media width you are trying to target:
#mixin media($width) {
#media only screen and (max-width: $width) {
#content;
}
}
#include media(320px) {
background: red;
}

Passing arguments from a mixin to a content block

This open issue in the Sass queue seems to imply passing arguments to #content is not a feature yet, but Susy 2 seems to be able to do this. Tracking down how it's done is a bit of a rabbit hole though and I haven't figured it out yet. Perhaps someone can shed some light with a straightforward example? I want to create a custom mixin that will inherit a layout passed from susy-breakpoint() using a custom map.
Example: Defining a 4 column layout in a global Sass map, will return a width of 100% when a span of 4 is specified inside susy-breakpoint()'s #content. When a custom layout of 8 cols is passed to directly tosusy-breakpoint() via the $layout argument, the nested span() mixin picks up the new layout. But a custom nested mixin will not pick up the new layout. Why?
#import 'susy';
$susy: (
columns: 4,
);
#mixin inherit-layout($layout: 4) {
columns: $layout;
}
#include susy-breakpoint(30em) {
// nested code uses an 4-column grid from global map
.global-cols {
#include span(4);
#include inherit-layout();
}
}
#include susy-breakpoint(48em, $layout: 8) {
// nested code uses an 8-column grid from $layout
.inherited-cols {
#include span(4);
#include inherit-layout();
}
}
Compiled CSS:
#media (min-width: 30em) {
.global-cols {
width: 100%;
float: left;
margin-left: 0;
margin-right: 0;
columns: 4;
}
}
#media (min-width: 48em) {
.inherited-cols {
width: 48.71795%;
float: left;
margin-right: 2.5641%;
columns: 4;
}
}
Update:
I've discovered that making the default variable for the inherit-value() mixin the value of columns key on the existing $susy map allows the mixin to grab context. But why? And why doesn't it work with a different map or outside of susy-breakpoint()?
See here: http://sassmeister.com/gist/d86e217aca3aa8337b83
Susy doesn't pass any arguments to the #content — instead, we change the global variable at the start of the content block, and then change it back at the end:
$example: 4;
#mixin local($local) {
$old: $example;
$example: $local !global;
#content
$example: $old !global;
}
// out here, $example == 4
#include local(12) {
// in here, $example == 12
}

sass compass magic sprites active state

I'm using compass to generate my icons and their hover states. The active state is the same as the hover state, and I'd like to keep my sprite map from being bloated with duplicate icons. Is there any way to make it add an active class to the same coordinates as the hover state?
#import 'sprites/*.png';
#include all-sprites-sprites;
generates:
.sprites-left {
background-position: 0 -16px;
}
.sprites-left:hover, .sprites-left.left_hover, .sprites-left.left-hover {
background-position: -18px -16px;
}
I'd like to add
.sprites-left.active {
background-position: -18px -16px;
}
This is as close to a solution as I could come up with.
#import 'sprites/*.png'; // sprites to include
#include all-sprites-sprites; // creates all sprites
// Manually extend each to add active states.
.sprites-engaged.active{ #extend .sprites-engaged:hover; }
.sprites-married.active{ #extend .sprites-married:hover; }
Did you read the docs? The Selector Control section covers this:
#import 'sprites/*.png';
.sprites-left {
&:hover, &.active { #include sprites-sprite(name_for_hover) }
... etc
}

Passing a list to a mixin in SASS as parameters?

I'm trying to make a SCSS stylesheet easily configurable by defining a set of constants that will be used in a number of mixins and with the Compass library. Ideally, I'd like to be able to do the following:
$item-bgs: linear-gradient(white, black), #ccc;
#mixin some-mixin() {
#include background-with-css2-fallback($item-bgs*);
}
The background-with-css2-fallback is a Compass mixin that accepts up to 10 params. I'm assuming that SASS does not currently support passing a list parameter as the argument list, otherwise Compass would probably use it, but I'm wondering if I can get the $item-bgs list to be the first 2 arguments to the background-with-css2-fallback mixin. Is there a way to do this currently, or is it even planned for SASS in the future?
It may not be supported by SASS natively, but Compass does support passing a list as the first argument to the background-with-css2-fallback mixin. If you look at the source for the mixin, you'll see that it uses a compact function that handles the logic for collapsing the arguments into a single list, whether passed individually or in a single list parameter.
For example, this works fine for me:
#import "compass";
$item-bgs: (linear-gradient(white, black), #ccc);
.test {
#include background-with-css2-fallback($item-bgs);
}
Examples of useing maps as arguments:
Example 1 (list)
#mixin transition($property...){
#if $property {
transition-property: $property;
}
#else {
transition-property: all;
}
transition-timing-function: ease-in-out;
transition-duration: .3s;
transition-delay: 0;
}
.btn {
color: black;
border: 1px solid black;
#include transition(color, border-color);
&:hover {
color: red;
border-color: red;
}
}
Example 2 (Custom params)
#use 'sass:meta';
#mixin example2($args...) {
#each $key, $value in meta.keywords($args) {
#{$key}: #{$value};
}
}
.shape {
#include example2($width:200px, $height:100px);
}
Example 3 (map)
#mixin colors($args:()) {
#if length($colors) > 0 {
#each $key, $val in $args{
.txt-#{$key} {
color: #{$value};
}
.bg-#{$key} {
background-color: #{$value};
}
}
}
}
$colors_map: (
primary: blue,
secondary: green,
accent: red,
light: white,
dark: black
);
#include colors($colors_map);

Resources