Is there a replace function/script in Sass to swap CSS properties? - css

I'm working on a right-to-left solution in Sass.
So for example, if the original style is:
#foo {
float: left;
padding-left: 10px;
}
...the function/script will run through looking for floats and padding-lefts and replace the styles with:
#foo {
float: right;
padding-right: 10px;
}
I already have a solution using mixins, like this:
#mixin float($origin: left) {
#if $origin == left {
#if $rtl { float: right; }
#else { float: left; }
} #else {
#if $rtl { float: left; }
#else { float: right; }
}
}
#mixin padding-left($value) {
padding-right: $value;
}
#foo {
#include float(left);
#include padding-left(10px);
}
...but is there a way to do this without having to replace all reversible properties with includes?

You could use a variable so you can set the direction in one place, but Sass doesn't have the ability to alter existing CSS based on rules you set.
$direc: left;
div {
float: $direc;
padding-#{$direc}: 10px;
}

Related

SASS mixin : how to add class before?

I'm struggling with creating a mixin with sass and I can't seem to find a solution. If anyone has any ideas...
I have something like this:
.tata {
font-size: 12px;
.toto{
display: block;
.tutu {
text-align: left;
#include mixin_test{
background: red;
}
}
}
}
and I'd like to have something like this when compiled:
html .tata .toto .tutu {background:red}
I've tried this, but the result is not what I expected:
#mixin mixin_test {
html{
#content;
}
}
Does anyone have a solution?
You need to edit your mixin. Missing & after the selector:
#mixin mixin_test {
html & {
#content;
}
}
.tata {
font-size: 12px;
.toto{
display: block;
.tutu {
text-align: left;
#include mixin_test{
background: red;
}
}
}
}
On this page you can read more about parent selector: Parent Selector

SASS Ampersand – Chaining CSS class with the parent selector '&' like in LESS

LESS (CSS)
see in action
.app {
#page {
.inner {
.left {
&.padding-left-10px {
padding-left: 10px;
// rtl direction
.rtl& { //////////////////////////////////
padding-left: 0;
padding-right: 10px;
}
}
}
}
}
}
Consider the line I have highlighted with ///.....
I want the same result in SASS (.scss). Is it possible?
Expected result should be:
.rtl.app #page .inner .left.padding-left-10px {}
and not
.rtl .app #page .inner .left.padding-left-10px {}
Thanks.
It looks like you are attempting to use the LESS feature where you can change the order of the selectors by using the parent selector. It isn't working as expected because that specific LESS feature isn't implemented the same way in SASS.
If you want the equivalent output code in SASS, then you can use the #at-root directive in order to scope the selector to the root. Then you would also need to use variable interpolation (i.e., .rtl#{&}) for the parent selector:
.app {
#page {
.inner {
.left {
&.padding-left-10px {
padding-left: 10px;
#at-root {
.rtl#{&} {
padding-left: 0;
padding-right: 10px;
}
}
}
}
}
}
}
Which would compile to:
.app #page .inner .left.padding-left-10px {
padding-left: 10px;
}
.rtl.app #page .inner .left.padding-left-10px {
padding-left: 0;
padding-right: 10px;
}
Josh gave you an answer which will work, i guess. But I still wanna give you some advice and that is look into BEM, or someway. Nesting like this is really unnecessary.
Your code could be better for readability.
For example:
.padding {
padding: 10px;
}
.padding--left { // This is a modifier for padding
padding: 0 0 0 10px;
}
.padding--right { // This is a modifier for padding
padding: 0 10px 0 0;
}
<div class="padding padding--left">Using it in a div</div>
You don't have to follow all the rules which are defined in BEM, but some are really nice to use.

How to change the number of automatic columns across media queries in Neat

Bourbon Neat allows you to use the span-column() mixin along with the omega() mixin to create automatic columns similar to foundation 5's block grids. However, these seem to fail miserably when sharing styles across media queries. Take a look at the example below:
.blocks {
#include media($iphone) {
#include span-column(4);
#include omega(3n);
}
#include media($ipad) {
#include span-column(3);
#include omega(4n);
}
}
It uses the nth-child position to remove the margin from the last item in the row, but when the media query happens it doesn't overwrite the other CSS if you are changing the omega. So the first media query will work as expected. Then when the $ipad query is triggered the nth-child(3n) remains in the CSS therefore breaking the $ipad query. Is there any way to get around this?
Compiled CSS:
.block-grid > li {
float: left;
display: block;
margin-right: 2.68967%;
width: 48.65516%;
}
.block-grid > li:last-child { margin-right: 0; }
.block-grid > li:nth-child(2n) { margin-right: 0; }
.block-grid > li:nth-child(2n+1) { clear: left; }
#media screen and (min-width: 1024px) {
.block-grid > li {
float: left;
display: block;
margin-right: 2.68967%;
width: 31.54022%;
}
.block-grid > li:last-child { margin-right: 0; }
.block-grid > li:nth-child(3n) { margin-right: 0; }
.block-grid > li:nth-child(3n+1) { clear: left; }
}
There is an 'omega reset' mixin that will deal with this: http://joshfry.me/notes/omega-reset-for-bourbon-neat/
Which does this:
#mixin omega-reset($nth) {
&:nth-child(#{$nth}) { margin-right: flex-gutter(); }
&:nth-child(#{$nth}+1) { clear: none }
}
So, to fix the code in the original question, put the omega-reset mixin in the proper place, and do this:
.blocks {
#include media($iphone) {
#include span-column(4);
#include omega(3n);
}
#include media($ipad) {
#include span-column(3);
#include omega-reset(3n); //added to reset previous omega value
#include omega(4n);
}
}
How you approach this with Bourbon/Neat is going to have to depend on how the #media mixin works. Your desired output is going to need to look something like this:
.block-grid > li {
float: left;
display: block;
margin-right: 2.68967%;
width: 48.65516%;
}
.block-grid > li:last-child { margin-right: 0; }
#media (max-width: 1024px) {
.block-grid > li:nth-child(2n) { margin-right: 0; }
.block-grid > li:nth-child(2n+1) { clear: left; }
}
So, if $ipad is just a pixel value, the absolute simplest way to accomplish this is by writing out your media query by hand using that variable:
.block-grid > li {
#include media($iphone) {
#include span-column(4);
}
#media (max-width: $ipad) {
#include omega(3n);
}
#include media($ipad) {
#include span-column(3);
#include omega(4n);
}
}
If it's the result of the new-breakpoint() function, then you'll just need to create another media query context using max-width (I'm just going by what I can glean from looking at the source/examples, so you'll have to forgive me if this isn't quite right):
$smaller-than-ipad: new-breakpoint(max-width 500px 12); // 12 = total columns, optional
.block-grid > li {
#include media($iphone) {
#include span-column(4);
}
#include media($smaller-than-ipad) {
#include omega(3n);
}
#include media($ipad) {
#include span-column(3);
#include omega(4n);
}
}

Using if statement on css selectors - SASS

I am working on a stylesheet for a multisite.
I have to declare a font-size in one variable, and the variable would change depending on the selectors. Eg:
$newfont : 10px;
i am attempting this which of course is not working:
#if ( #header ) {
$newfont: 30px;
}# else if ( #footer ) {
$newfont: 25px;
}
Can someone please point out what i am doing wrong?
I am sorry but why don't you use
#header{
font-size: 30px;
}
#footer{
font-size:25px;
}
and as pointed out in the comment below you can use a mixin.
I'm not sure what you are trying to achieve, but #if requires a SassScript expression. What you are passing is actually a selector. If you want to apply different font size for different containers I'll suggest to use a function or mixin. For example:
#function get-font-size($type) {
#if $type == "header" {
#return 30px;
} #else if $type == "footer" {
#return 25px;
}
}
#header {
font-size: get-font-size("header");
}
#footer {
font-size: get-font-size("footer");
}
The code produces:
#header {
font-size: 30px;
}
#footer {
font-size: 25px;
}
You may even control the process with a variable as you tried actually:
$newfontsize: 30px;
#mixin update-font-size($size) {
$newfontsize: $size;
}
#function get-font-size() {
#return $newfontsize;
}
#header {
font-size: get-font-size();
}
#include update-font-size(15px);
#footer {
font-size: get-font-size();
}
The simplest solution is to just use more variables. This is how most theming libraries do it.
$header-font-size: 30px !default;
$footer-font-size: 25px !default;
#header{
font-size: $header-font-size;
}
#footer{
font-size: $footer-font-size;
}

SASS mixin for swapping images / floats on site language (change)

Currently using SASS on a website build. It is my first project using it, tried a little LESS before and liked it. I made a few basic mixins and variables with LESS, super useful stuff!
I am trying to get my head around SASS mixins, and syntax, specifically for swapping images when the page changes to a different language, be that with body ID changing or <html lang="en">. And, swapping floats around if, for example, a website changed to Chinese. So a mixin where float left is float left unless language is AR and then it becomes float right.
With LESS I think it would be something like:
.headerBg() when (#lang = en) {background-image:url(../img/hello.png);}
.headerBg() when (#lang = it) {background-image:url(../img/ciao.png);}
.header {.headerBg(); width: 200px; height:100px}
.floatleft() when (#lang = en) { float: left;}
.floatleft() when (#lang = ar) { float: right;}
.logo {.floatleft();}
It's the syntax I am having problems with.
I'd probably use the #content feature and do something like this:
#mixin headerBg {
.header {
#content
}
}
#mixin floatDir {
.logo {
#content
}
}
:lang(en) {
#include headerBg {
background-image:url(../img/hello.png);
}
#include floatDir {
float: left;
}
}
:lang(ar) {
#include headerBg {
background-image:url(../img/ciao.png);
}
#include floatDir {
float: right;
}
}
Which compiles to:
:lang(en) .header {
background-image: url(../img/hello.png); }
:lang(en) .logo {
float: left; }
:lang(ar) .header {
background-image: url(../img/ciao.png); }
:lang(ar) .logo {
float: right; }
If the background image names where based on the language, then it might make sense to use #each and do something like this:
#each $lang in en, ar {
:lang(#{$lang}) {
#if $lang == en {
.logo {
float: left;
}
} #else if $lang == ar {
.logo {
float: right;
}
}
.header {
background-image:url(../img/#{$lang}.png);
}
}
}
Which compiles to:
:lang(en) .logo {
float: left; }
:lang(en) .header {
background-image: url(../img/en.png); }
:lang(ar) .logo {
float: right; }
:lang(ar) .header {
background-image: url(../img/ar.png); }

Resources