Question: With SCSS, can we specify two different .main selectors? Say I want another one with margin-top: 50px while also inheriting all other conditions
I have inherited some SCSS from someone else. I have the following SCSS structure:
.main {
margin-top: 74px;
ul.tabs {
position: relative;
li.tab {
/*The rest of nested structure*/
}
}
}
It continues to nest (unfortunately) for many layers.
I have some other options (splitting the structure in two) which is a simple fix. Just curious if there's something better.
Thanks!
You should use a mixin:
#mixin sharedStyles{
//shared nested styles go here
}
.parentA{
margin-top:74px;
#include sharedStyles;
}
.parentB{
margin-top: 50px;
#include sharedStyles;
}
Here is a gist that illustrates the concept:
https://gist.github.com/Ryan-Haines/ba10888d0828d394851d3da6063f70bb
I recommend using sassmeister for rapid prototyping:
https://www.sassmeister.com
If you use a placeholder, as long as one selector is not inside a media query, it should group them together in the CSS. Ie
%mainStyles {
border: 1px solid black;
}
.main1 {
margin-top: 75px;
#extend %mainStyles;
}
.main2 {
margin-top: 50px;
#extend %mainStyles;
}
Should generate
.main1, .main2 {
border: 1px solid black;
}
.main1 {
margin-top: 75px;
}
.main2 {
margin-top: 50px;
}
Related
I have a project made with react and I want to optimize the css.
I have this code:
.class-1 {
margin-top: 15px;
}
.class-2 {
margin-bottom: 15px;
}
Is there a possible way to optimize like this during the build?
.class-3 {
margin: 15px 0 15px 0;
}
You can add both classes to your HTML element or combine the margins into one class like this:
.class1 {
margin-top: 15px;
background-color: skyblue;
}
.class2 {
margin-bottom: 15px;
}
.class3 {
margin: 15px 0;
background-color: red;
}
<div class='class1 class2'>My element with 2 classes</div>
<div class='class3'>My element with 1 class</div>
It all depends if you want to keep the classes separate for other areas of your code, or if you will never need those margins in separate classes.
I just finished with the Sass guide.
The guide explains mixins:
..A mixin lets you make groups of CSS declarations that you want to
reuse throughout your site. You can even pass in values to make your
mixin more flexible.
and extend:
.. This is one of the most useful features of Sass. Using #extend lets
you share a set of CSS properties from one selector to another ..
It looks like 'extend' may be implemented in 'mixin' (it seems 'mixin' is extend of 'extend' :-) ).
// #extend
.message {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}
.success {
#extend .message;
border-color: green;
}
.error {
#extend .message;
border-color: red;
}
.warning {
#extend .message;
border-color: yellow;
}
// #mixin
#mixin message($color) {
border: 1px solid #ccc;
padding: 10px;
color: #333;
border-color: $color;
}
.success { #include message(green); }
.error { #include message(red); }
.warning { #include message(yellow); }
and even more because mixins have params.
But on the other hand the processed CSS is not exactly the same. But it will be same style effect on the DOM.
/* extend processed */
.message, .success, .error, .warning {
border: 1px solid #ccc;
padding: 10px;
color: #333; }
.success {
border-color: green; }
.error {
border-color: red; }
.warning {
border-color: yellow; }
/* mixin processed */
.success {
border: 1px solid #ccc;
padding: 10px;
color: #333;
border-color: green; }
.error {
border: 1px solid #ccc;
padding: 10px;
color: #333;
border-color: red; }
.warning {
border: 1px solid #ccc;
padding: 10px;
color: #333;
border-color: yellow; }
My question is how do these features differ?
When should I use one over the other?
From http://blog.nakulrajput.com/mixins-extends-and-placeholders/:
#mixin
Here is how mixins work. Definition and usage:
#mixin awesome {
width: 100%;
height: 100%;
}
body {
#include awesome;
}
p {
#include awesome;
}
The snippets above produce the following CSS:
body {
width: 100%;
height: 100%;
}
p {
width: 100%;
height: 100%;
}
To make things a little bit more interesting, we could make our mixin accept parameters. Even better, we are able to define default values if the mixin is called without arguments.
#mixin awesome($w: 100%, $h: 100%) {
width: $w;
height: $h;
}
body {
#include awesome(960px);
}
p {
#include awesome;
}
The result will be similar, but the width of the body is different.
body {
width: 960px;
height: 100%;
}
p {
width: 100%;
height: 100%;
}
If you use mixins, the styles in them are duplicated for each selector.
Mixins are very helpful if you need to change or calculate something in the final output, for example if you need to apply border-radius to several elements.
However, in some other cases there is a lot of duplicative code, which could be avoided if you use #extend.
**#extend**
.awesome {
width: 100%;
height: 100%;
}
body {
#extend .awesome;
}
p {
#extend .awesome;
}
It's similar, isn't it. In Sass it looks almost identical, but the CSS the result is:
.awesome, body, p {
width: 100%;
height: 100%;
}
Shorter than the version using a mixin. You can't pass parameters during the extending, but that's not the idea actually.
#extend should be used in those places where you want to share properties between the elements.
Well, Mixin is like function that can do some work and output processed result while extend is like pre-defined cop-paste code
In programming terms:
#include is like calling a function with or without parameters
#extend is like Inheritance
Function means, every time we call the function, the body of the function gets duplicated as we might pass dynamic information in the form of parameters. so you would get a Copy of the body.
Inheritance means, there is no duplication and we get a Reference instead of copy. so who ever extends that reference would get the same body.
I'm pretty new to CSS and have been finding my way around so far.
I am creating these button like links with shadows and stuff. Now there are several such buttons required on the site - everything about the buttons is same - except few properties change like width and font size.
Now instead of copying the same code - over and over for each button - is there a way of extending the button and adding just the properties that change.
Example of two buttons - css
.ask-button-display {
background: #8BAF3B;
border-radius: 4px;
display: block;
letter-spacing: 0.5px;
position: relative;
border-color: #293829;
border-width: 2px 1px;
border-style: solid;
text-align:center;
color: #FFF;
width:350px;
font-size: 20px;
font-weight: bold;
padding:10px;
}
.ask-button-submit {
background: #8BAF3B;
border-radius: 4px;
display: block;
letter-spacing: 0.5px;
position: relative;
border-color: #293829;
border-width: 2px 1px;
border-style: solid;
text-align:center;
color: #FFF;
font-weight: bold;
width:75px;
font-size: 12px;
padding: 1px;
}
And this is how I'm currently using it in my html
Ask a Question Submit
So I'm wondering if there is a cleaner way to do this - like
.button {
/* PUT ALL THE COMMON PROPERTIES HERE */
}
AND THEN SOMEHOW EXTEND IT LIKE
.button #display {
/* THE DIFFERENT PROPERTIES OF Display BUTTON */
}
.button #ask {
/* THE DIFFERENT PROPERTIES OF Ask BUTTON */
}
But I'm not sure how to do this.
Thanks for your inputs
You can add multiple classes to one element, so have one .button class which covers everything, then a .button-submit class, which adds things in.
For example:
.button {
padding: 10px;
margin: 10px;
background-color: red;
}
.button-submit {
background-color: green;
}
See a live jsFiddle here
In your case, the following should work:
.button {
background: #8BAF3B;
border-radius: 4px;
display: block;
letter-spacing: 0.5px;
position: relative;
border-color: #293829;
border-width: 2px 1px;
border-style: solid;
text-align:center;
color: #FFF;
width:350px;
font-size: 20px;
font-weight: bold;
padding:10px;
}
.button-submit {
width:75px;
font-size: 12px;
padding: 1px;
}
See a live jsFiddle here
You might want to try this:
.button {
padding: 10px;
margin: 10px;
background-color: red;
}
.button.submit {
background-color: green;
}
.button.submit:hover {
background-color: #ffff00;
}
This way you avoid repeating the word and will able to use the classes in the elements like this:
Ask a Question
Submit
See the example in JSFiddle (http://goo.gl/6HwroM)
Rather than repeat the common "Add a button class to the element" answer I'm going to show you something new in the weird and whacky world of new age CSS, or better known as SCSS!
This reuse of code in stylesheets can be achieved with something called a 'Mixin'. What this allows us to do is reuse certain styles by using the '#include' attribute.
Let me give you an example.
#mixin button($button-color) {
background: #fff;
margin: 10px;
color: $color;
}
and then whenever we have a button we say
#unique-button {
#include button(#333);
...(additional styles)
}
Read more here: http://sass-lang.com/tutorial.html.
Spread the word!!!
You can do this since you can apply more than one class to an element. Create your master class and and other smaller classes and then just apply them as needed. For example:
Ask a Question Submit
This would apply the button and submit classes you would create while allowing you to also apply those classes separately.
Modify your code example along the lines of:
.master_button {
/* PUT ALL THE COMMON PROPERTIES HERE */
}
AND THEN SOMEHOW EXTEND IT LIKE
.button_display {
/* THE DIFFERENT PROPERTIES OF Display BUTTON */
}
.button_ask {
/* THE DIFFERENT PROPERTIES OF Ask BUTTON */
}
And apply like:
Ask a Question
Submit
.ask-button-display,
.ask-button-submit {
/* COMMON RULES */
}
.ask-button-display {
}
.ask-button-submit {
}
You may want to look into Sass. With Sass you can basically create variables in your css file and then re-use them over and over. http://sass-lang.com/
The following example was taken from Sass official website:
$blue: #3bbfce;
$margin: 16px;
.content-navigation {
border-color: $blue;
color:
darken($blue, 9%);
}
.border {
padding: $margin / 2;
margin: $margin / 2;
border-color: $blue;
}
Add a button class to both links for the common parts
.button {
background: #8BAF3B;
border-radius: 4px;
display: block;
letter-spacing: 0.5px;
position: relative;
border-color: #293829;
border-width: 2px 1px;
border-style: solid;
text-align:center;
color: #FFF;
}
Keep in your other classes the rules that aren't common.
And your HTML will be
Ask a Question
Submit
Without changing/ adding new classes you can add styles to all elements with a class name starting with "ask-button"... (whatever the elements with the class are; button, anchor, div etc.) let's say your buttons are divs then:
div[class^="ask-button"] {
// common css properties
}
You can also list all classes that will have common properties like this:
.ask-button-display,
.ask-button-submit {
// common css properties here
}
And then you add the separate styling for each button:
.ask-button-display{
// properties only for this button
}
.ask-button-submit {
// properties only for this button
}
I'm currently working on a team that uses SASS. I see that we are extending styles that are very simple and to me I don't see the benefit of doing this. Am I missing something?
Here are some examples of a _Common.scss that is imported and used throughout other sass files:
.visibility-hidden{visibility: hidden;}
.display-inline { display: inline; }
.display-inline-block { display: inline-block; }
.display-block { display: block; }
.display-none { display: none; }
.display-box { display: box; }
.float-left { float: left; }
.float-right { float: right; }
.clear-both { clear: both; }
.width-percent-100 { width: 100%; }
.width-percent-65 { width: 65%; }
.width-percent-50 { width: 50%; }
.width-percent-45 { width: 45%; }
.width-percent-40 { width: 40%; }
.width-percent-33 { width: 33%; }
.width-percent-30 { width: 30%; }
.width-percent-20 { width: 20%; }
.height-percent-100 { height: 100%; }
.cursor-pointer { cursor: pointer; }
.underline { text-decoration: underline; }
.text-decoration-none { text-decoration: none; }
.bold { font-weight: bold; }
.font-weight-normal { font-weight: normal; }
.text-align-center { text-align: center; }
.text-align-left { text-align: left; }
.text-align-right { text-align: right; }
.font-10 { font-size: 10px; }
.font-11 { font-size: 11px; }
.font-12 { font-size: 12px; }
.font-13 { font-size: 13px; }
.font-14 { font-size: 14px; }
.font-15 { font-size: 15px; }
.font-16 { font-size: 16px; }
.font-17 { font-size: 17px; }
.font-18 { font-size: 18px; }
.font-percent-65 { font-size: 65%; }
.font-percent-80 { font-size: 80%; }
.font-percent-90 { font-size: 90%; }
.font-percent-100 { font-size: 100%; }
.font-percent-110 { font-size: 110%; }
.font-percent-120 { font-size: 120%; }
.font-percent-130 { font-size: 130%; }
.font-percent-140 { font-size: 140%; }
.font-percent-150 { font-size: 150%; }
.font-percent-160 { font-size: 160%; }
.font-percent-170 { font-size: 170%; }
.font-percent-180 { font-size: 180%; }
Example:
#CategoriesContainer
{
ul{
li{
&:first-child{
#extend .font-11;
}
a
{
#extend .font-11;
#extend .text-decoration-none;
}
}
}
}
You should only use extend when you have a certain attribute set that will be used multiple times. The sheer stupidy of extending a class with a class with one attribute that has the unit value worked into the name of it is incomprehensible.
A better example for a reason to extend can be found in the reference guide
Say we have 2 classes
.error {
border: 1px #f00;
background-color: #fdd;
}
.seriousError {
border-width: 3px;
}
.error is a general no interesting style but a serious error should be really clear.
.seriousError is created to thicken the line, the only problem is that now we have to use both classes in the html to combine the styles.
Because we're lazy and just want to use one class and not duplicate code that might be changed in the future we can extend .seriousError with .error
.seriousError {
#extend .error;
border-width: 3px;
}
Now we didn't duplicate the code in our sass file but did get the right styles on the page.
Check out the reference guide for more/better examples.
Just please for the sake of kittens stop extending classes with one attribute classes. And don't implicitly state the value/attributes in the selector, thats not very semantic.
You, and your team, should read this post which explains a few problems with the aproach you take here vs semantic code. Couldn't find a better tuned post this quick.
You aren't missing anything, this is just bloated code in poor form and not a great way to extend classes.
There is maybe one (bad) reason I can imagine why this would be used. If for example .font-10 needs to be .7em instead of 10px, it can be easily changed - but then you've just defeated the point of naming the class "font10". Something like small-font would even make more sense in that case (and I'm not suggesting you use that either).
I won't discuss the merits of semantic class names and the folly of presentational ones (especially as literal as these are), but I will suggest that this is a very narrow use of extending classes. With a 1:1 mapping of class name to property/value, you've practically defeated the purpose of #extend, which is supposed to make you write less CSS.
Better example of what to use #extend for:
.media {
padding:1em;
border-color:blue;
background-color:red;
clear:left;
}
.my-media {
#extend .media;
background-color:green;
}
Atomic CSS
The technique of very simple CSS rules does have a bit of precedent - at Yahoo! they call it Atomic CSS. Thierry Koblentz argues in this Smashing Magazine article for using the simple classes directly in your markup, similar to inline styling. This can be helpful on very large projects across multiple web properties, where styles are not consistent. Base styles for OOCSS components can't be reused as much in such a situation, causing you to have to write many more lines of extension classes or overrides.
The downside is, of course, as Wesley mentioned, that it is much more difficult to make changes across your entire project's styles, such as updating the text size of a specific selector.
I've been playing around with a variant of this technique recently in a fairly large project, where styles can often be one-off. In an effort to avoid the I try to avoid putting hard values directly in the selectors. For instance, the following css (example fiddle):
_colors.scss
.text-white {
color: $white;
}
.blue {
#extend .text-white;
background: $blue;
}
_effects.scss
.circle {
width: 50px;
height: 50px;
border-radius: 50%;
text-align: center;
line-height: 50px;
font-size: 40px;
}
.matted {
border: 4px solid $white;
}
.shadow {
#include box-shadow(0 1px 4px 1px rgba($black, 0.25));
}
HTML:
<div class="blue matted circle shadow">?</div>
Specificity issues
One last thing to keep in mind if you decide to use this technique - it can cause specificity problems if you're extending base-level classes that use the same CSS properties. For instance, in the following example (fiddle), how would your border-radius appear? You wanted the top to be squared off (no border-radius) but this isn't happening, because the .circle class is further down in your css and just as specific (single class) as the other effects. This is a bit of a contrived example, but if you reuse CSS properties across your atomic selectors, this can be a real problem.
_colors.scss
.text-white {
color: white;
}
.blue {
#extend .text-white;
background: royalblue;
}
_effects.scss
.squared-top {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.rounded {
border-radius: 10px;
}
.circle {
width: 50px;
height: 50px;
border-radius: 50%;
}
HTML:
<span class="circle blue rounded squared-top"></span>
If you do it that way you can also use it directly in the HTML - so it looks like they took the OOCSS path and because it's already in the CSS you can now also extend to it. Very flexible but it could also turn very messy.
Extend option is used poorly here. It should be used for extending classes with more content and in that case extend can be very helpful.You can find more about extend and its options here.
I have a simple border style say:
.border
{
/*content*/
}
I want several other classes to inherit this border style. Can this be done in CSS only?
Or do I need to specify it in HTML also?
I want:
.actionArea : .border
{
/*content */
}
Or can this only be done in HTML like:
<div class="actionArea border"/>
It would be very annoying if the latter is only possible.
Update
This works good enough, but still is a bit ugly:
.actionArea, .otherArea, .anotherArea
{
/*border specification */
}
.actionArea
{
/*area specification/*
}
.otherArea
{
/*area specification/*
}
(..)
You will need to use a CSS framework such as LESS for such a thing.
You may use sass . Probably it is the nesting feature you want to use http://sass-lang.com/#nesting
table.hl {
margin: 2em 0;
td.ln {
text-align: right;
}
}
li {
font: {
family: serif;
weight: bold;
size: 1.2em;
}
}
Or as Oded said you can use LESS . LESS is having some interesting feature one of them is mixins . This is not exactly inheritance but it gives you has-a relationship in css
Example copied from LESS
.bordered {
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
#menu a {
color: #111;
.bordered;
}
.post a {
color: red;
.bordered;
}