Sass (SCSS) - How to Add to Individual Values in a Class - sass

I want to add 2px to the padding all around an element. So
padding: 10px 14px;
will become
padding: 14px 18px;. How can I achieve this?
Hopefully there is a more elegant solution than (psuedo-code):
$horizontal-padding: 10;
$vertical-padding: 14;
.normal-padding {
padding-top: $vertical-padding;
padding-right: $horizontal-padding;
padding-bottom: $vertical-padding;
padding-left: $horizontal-padding;
}
.extra-padding {
($horizontal-padding + 2 + px), ($vertical-padding + 2 + px);
}
Surely there must be a better way?

Actually, you can write that in a lot of ways. A solution similar to your code could be:
$vertical-padding: 14px;
$horizontal-padding: 10px;
.normal-padding {
padding: $vertical-padding $horizontal-padding;
}
.normal-padding {
$extra: 2px;
padding: #{$vertical-padding + $extra} #{$horizontal-padding + $extra};
}
A more dynamical way (not really useful if you only have these two variations though):
#mixin padding($extra : 0) {
padding: #{14 + $extra}px #{10 + $extra}px;
}
.normal-padding {
#include padding;
}
.extra-padding {
#include padding(2);
}
You can even change the code above to keep the $vertical-padding and $horizontal-padding variables. As I said, there are many ways to do it.

Just for fun. You can use css custom properties:
div {
border: 1px solid;
}
:root {
/* declare global variables */
--padding-x: 10px;
--padding-y: 10px;
}
.padded {
padding: var(--padding-y) var(--padding-x);
}
.extra {
/* redefine variables for `extra` elements */
--padding-x: 30px;
--padding-y: 30px;
}
<div class="padded"></div>
<div class="padded extra"></div>

Related

Not able to find pre-defined sass variables in Jekyll project

I'm new the Jeykll and Sass and have a quick question. Within the pre-built theme when starting a new project, where are these variables defined?
I can't seem to find them aware through out the build.
This is in the _sass/layout.scss directory.
*/
.site-header {
border-top: 5px solid $grey-color-dark;
border-bottom: 1px solid $grey-color-light;
min-height: 56px;
// Positioning context for the mobile navigation icon
position: relative;
}
.site-title {
font-size: 26px;
line-height: 56px;
letter-spacing: -1px;
margin-bottom: 0;
float: left;
&,
&:visited {
color: $grey-color-dark;
}
}
.site-nav {
float: right;
line-height: 56px;
.menu-icon {
display: none;
}
.page-link {
color: $text-color;
line-height: $base-line-height;
// Gaps between nav items, but not on the first one
&:not(:first-child) {
margin-left: 20px;
}
}
#include media-query($on-palm) {
position: absolute;
top: 9px;
right: 30px;
background-color: $background-color;
border: 1px solid $grey-color-light;
border-radius: 5px;
text-align: right;
.menu-icon {
display: block;
float: right;
width: 36px;
height: 26px;
line-height: 0;
padding-top: 10px;
text-align: center;
> svg {
width: 18px;
height: 15px;
path {
fill: $grey-color-dark;
}
}
}
.trigger {
clear: both;
display: none;
}
&:hover .trigger {
display: block;
padding-bottom: 5px;
}
.page-link {
display: block;
padding: 5px 10px;
}
}
}
/**
* Site footer
*/
.site-footer {
border-top: 1px solid $grey-color-light;
padding: $spacing-unit 0;
}
.footer-heading {
font-size: 18px;
margin-bottom: $spacing-unit / 2;
}
.contact-list,
.social-media-list {
list-style: none;
margin-left: 0;
}
.footer-col-wrapper {
font-size: 15px;
color: $grey-color;
margin-left: -$spacing-unit / 2;
#extend %clearfix;
}
.footer-col {
float: left;
margin-bottom: $spacing-unit / 2;
padding-left: $spacing-unit / 2;
}
.footer-col-1 {
width: -webkit-calc(35% - (#{$spacing-unit} / 2));
width: calc(35% - (#{$spacing-unit} / 2));
}
.footer-col-2 {
width: -webkit-calc(20% - (#{$spacing-unit} / 2));
width: calc(20% - (#{$spacing-unit} / 2));
}
.footer-col-3 {
width: -webkit-calc(45% - (#{$spacing-unit} / 2));
width: calc(45% - (#{$spacing-unit} / 2));
}
#include media-query($on-laptop) {
.footer-col-1,
.footer-col-2 {
width: -webkit-calc(50% - (#{$spacing-unit} / 2));
width: calc(50% - (#{$spacing-unit} / 2));
}
.footer-col-3 {
width: -webkit-calc(100% - (#{$spacing-unit} / 2));
width: calc(100% - (#{$spacing-unit} / 2));
}
}
#include media-query($on-palm) {
.footer-col {
float: none;
width: -webkit-calc(100% - (#{$spacing-unit} / 2));
width: calc(100% - (#{$spacing-unit} / 2));
}
}
/**
* Page content
*/
.page-content {
padding: $spacing-unit 0;
}
.page-heading {
font-size: 20px;
}
.post-list {
margin-left: 0;
list-style: none;
> li {
margin-bottom: $spacing-unit;
}
}
.post-meta {
font-size: $small-font-size;
color: $grey-color;
}
.post-link {
display: block;
font-size: 24px;
}
/**
* Posts
*/
.post-header {
margin-bottom: $spacing-unit;
}
.post-title {
font-size: 42px;
letter-spacing: -1px;
line-height: 1;
#include media-query($on-laptop) {
font-size: 36px;
}
}
.post-content {
margin-bottom: $spacing-unit;
h2 {
font-size: 32px;
#include media-query($on-laptop) {
font-size: 28px;
}
}
h3 {
font-size: 26px;
#include media-query($on-laptop) {
font-size: 22px;
}
}
h4 {
font-size: 20px;
#include media-query($on-laptop) {
font-size: 18px;
}
}
}
Notice: Jekyll has since been updated, its default theme, minima, is now in a separate gem, and the definitions are there, in _sass/minima.scss.
Look at this, with relative path to site root in default Jekyl site css/main.scss. There they are. After all the definitions, imports and processing, there will be css/main.css in the resulting site.
Everything in _sass is just for importing into real assets that will be converted to CSS. The difference between Sass/SCSS files in _sass and everywhere else is that files from _sass are not compiled directly, but rather just lay where they are and wait to be imported. Every possibly reusable piece of Sass should be in _sass, that's what Sass partials and this system overall is designed for. This is especially useful if you use a lot of Sass libraries (like I do, and it's still a mess) and don't want them to be modified in order to be put into your assets.
All the other files (not in _sass), however, will be processed into corresponding *.css files, and in order to distinguish files for processing, Jekyll requires such files to have a YAML front-matter, usually empty.
---
---
// Sass code here
(I used to utilize Liquid for embedding variables in Sass, but that feature vanished after some updates, so now non-empty YFM in assets is of no use now).

SCSS repeat value?

I'm trying to work out on SCSS how I would go about something like this:
I would like to have a margin anywhere between 1px and 1000px and have a class for it.
For example
.MarginTop-x
X being where I can write any value. Obviously I couldn't write out
.MarginTop-1 {margin-top:1px}
.MarginTop-2 {margin-top:2px}
.MarginTop-3 {margin-top:3px}
.MarginTop-4 {margin-top:4px}
etc...
Well you need a #for loop to do that .
SCSS :
$class-slug: ".MarginTop";
$stop-loop: 4;
#for $i from 0 through $stop-loop {
#{$class-slug}-#{$i} {
margin-top: #{$i}px;
}
}
Compiled CSS:
.MarginTop-0 {
margin-top: 0px; }
.MarginTop-1 {
margin-top: 1px; }
.MarginTop-2 {
margin-top: 2px; }
.MarginTop-3 {
margin-top: 3px; }
.MarginTop-4 {
margin-top: 4px; }
Not sure of the utility of this, but...
Sass:
#mixin marginTop($amount) {
.marginTop-#{$amount} {
margin-top: unquote($amount + 'px');
}
}
#include marginTop(1);
#include marginTop(100);
Compiled CSS:
.marginTop-1 {
margin-top: 1px;
}
.marginTop-100 {
margin-top: 100px;
}

Incrementing Variable in Loop

I've got the following loop producing some styles for a tag cloud. On the online generators it produces the I'd consider the correct css styles, however in the visual studio solution (2012) which auto produces the css it seems to hang up. (see below) the less. Is there a more proper way to produce something like this via less that won't confuse the VS .less generator?
#iterations: 10;
#maxSize: 40;
#minSize: 10;
.tag-loop (#i) when (#i > -1) {
#j: (#i*(30/#iterations) + #minSize);
li.tag-#{i} {
font-size:~"#{j}px";
}
.tag-loop(#i - 1);
}
.tag-loop (#iterations);
Produces via visual studio:
ul.tag-cloud li.tag-10 {
font-size: 10px;
}
ul.tag-cloud li.tag-9 {
font-size: 10px;
}
ul.tag-cloud li.tag-8 {
font-size: 10px;
}
ul.tag-cloud li.tag-7 {
font-size: 10px;
}
ul.tag-cloud li.tag-6 {
font-size: 10px;
}
ul.tag-cloud li.tag-5 {
font-size: 10px;
}
ul.tag-cloud li.tag-4 {
font-size: 10px;
}
ul.tag-cloud li.tag-3 {
font-size: 10px;
}
ul.tag-cloud li.tag-2 {
font-size: 10px;
}
ul.tag-cloud li.tag-1 {
font-size: 10px;
}
ul.tag-cloud li.tag-0 {
font-size: 10px;
}
If I use something like http://winless.org/online-less-compiler the following is more accurately produced:
li.tag-10 {
font-size: 40px;
}
li.tag-9 {
font-size: 37px;
}
li.tag-8 {
font-size: 34px;
}
li.tag-7 {
font-size: 31px;
}
li.tag-6 {
font-size: 28px;
}
li.tag-5 {
font-size: 25px;
}
li.tag-4 {
font-size: 22px;
}
li.tag-3 {
font-size: 19px;
}
li.tag-2 {
font-size: 16px;
}
li.tag-1 {
font-size: 13px;
}
li.tag-0 {
font-size: 10px;
}
It looks like your VS uses (via Web Essentials 2012?) quite outdated Less 1.3.3 which handles variable scope quite differently, i.e. #j defined in the last iteration overrides all previous #j definitions.
The workaround to this is to calculate font-size value directly:
#iterations: 10;
#maxSize: 40;
#minSize: 10;
.tag-loop (#i) when (#i > -1) {
li.tag-#{i} {
font-size: unit((#i * (30 / #iterations) + #minSize), px);
}
.tag-loop((#i - 1));
}
.tag-loop (#iterations);

Custom directives within scss files? Perhaps for a new pseudo class?

Is it be possible to use some sort of #directive creation syntax, similar to creating #mixins? Secondly, is it possible to create a SASS-only pseudo class?
I'd like to declare my own SASS directive,although I'd prefer not to have to force my teammates to install an extra ruby gem to use it so I'd want to store it in a scss partial. I do understand that they are orders of levels in complexity, so perhaps it just isn't possible.
In addition to perhaps creating a new scss-only pseudo class (such as :parent, :clicked, :unchecked, etc) I'd be interested in a custom-made directive that assists with using checkboxes to direct css animations ("css checkbox hack"). Here is my scss pseudocode to generalize what I'm trying to do:
// this code monitors when a checkbox (#someinput) is checked,
// then applies style to div #target div. Basically an 'onClick' event in scss.
body {
#wrapper {
#targetdiv {
#spotcheck(#someinput) { #
color: red; border: 2px solid blue; # <-- move this ...
} #
color: blue; border: 0;
#someinput {
width: 20px; height: 20px;
}
}
}
}
// ... the above scss should be converted to this pre-compiled state, also scss
body {
#someinput:checked ~ #targetdiv { #
color: red; border: 2px solid blue; # <-- ..to here. it needs to be
} # above the #targetdiv
#wrapper {
#targetdiv {
color: blue; border: 0;
#someinput {
width: 20px; height: 20px;
}
}
}
}
Make your selectors only as specific as they absolutely need to be and no more. A mixin would only be more verbose with no real benefit.
#targetdiv {
color: blue; border: 0;
#someinput:checked ~ & {
color: red; border: 2px solid blue;
}
}
#someinput {
width: 20px; height: 20px;
}
Output:
#targetdiv {
color: blue;
border: 0;
}
#someinput:checked ~ #targetdiv {
color: red;
border: 2px solid blue;
}
#someinput {
width: 20px;
height: 20px;
}
Alternately, this would give the same result with the ability to overqualify as much as you want:
#targetdiv {
color: blue; border: 0;
}
#someinput {
width: 20px; height: 20px;
~ #targetdiv {
color: red; border: 2px solid blue;
}
}

Use a parameter as a tag in a mixin

How can I do that :
#mixin addMargin($el) {
$el {
margin-left: 5px;
}
$el:hover {
margin-left: 10px;
}
}
using sass ?
Thanks for your help
In a mixin, you can not only add properties directly to an element, but you can also add more rules:
#mixin addMargin {
margin-left: 5px;
&:hover {
margin-left:10px;
}
}
Note that you have to prefix the :hover with & so that we get this rule:
#something-with-the-mixin-applied:hover
instead of
#something-with-the-mixin-applied :hover
Use interpolation:
#mixin addMargin($el) {
#{$el} {
margin-left: 5px;
}
#{$el}:hover {
margin-left: 10px;
}
}
#include addMargin(h1);
But Yogu is right, you don't need it here. You may omit selectors, leaving only directives in your mixin, and apply the mixin inside a selector:
#mixin addMargin {
margin-left: 5px;
&:hover {
margin-left:10px;
}
}
h1 {
#include addMargin;
}

Resources