How to avoid duplicate entries in SCSS/SASS? - css

I have recently started working with SASS in combination with Eclipse at work, and everything's working peachy:
Building an application through Ant executes a .bat which runs a Ruby command line which compiles any relevant .scss files into .css files.
One thing we've noticed however is that there can be duplicates. Granted, the general .css overrule rules apply (last one first), but having x-amount of the same statement is quite redundant. Take a a look at the following example of compiles .css code (it's not perfect, I was merely testing something)
/* line 2, ../../../sass/common/style.scss */
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
/* line 8, ../../../sass/common/style.scss */
nav li {
display: inline-block;
}
/* line 9, ../../../sass/common/style.scss */
nav li {
display: inline-block;
}
/* line 11, ../../../sass/common/style.scss */
nav a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
/* line 1, ../../../sass/webshop/_button-style.scss */
div:hover {
padding: 12px 12px;
}
/* line 5, ../../../sass/webshop/_button-style.scss */
img {
padding: 12px 24px;
}
/* line 2, ../../../sass/webshop/_webshop-style.scss */
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
/* line 8, ../../../sass/webshop/_webshop-style.scss */
nav li {
display: inline-block;
}
/* line 9, ../../../sass/webshop/_webshop-style.scss */
nav li {
display: inline-block;
}
/* line 11, ../../../sass/webshop/_webshop-style.scss */
nav a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
/* line 18, ../../../sass/webshop/_webshop-style.scss */
div:hover {
padding: 12px 12px;
}
In this test style.scss contains the main styling for the webshop, _button-style.scss for any buttons present and _webshop-style contains any overrules for style.scss.As you can see, there are duplicates from style.scss and _webshop-style.scss present in this file, which is something we'd rather avoid. Can this be avoided? If yes: How?; If no: Is there a workaround/manual method to avoid this?
NOTE: _button-style.css is of no importance to this question/problem. It's just here to show you in a complete way what I'm doing.
For further reference, here's some important files:
config:
require 'compass/import-once/activate'
require "sass-globbing"
# Require any additional compass plugins here.
# Set this to the root of your project when deployed:
#http_path = "/"
css_dir = "../webapp/static/css"
sass_dir = "common"
add_import_path = "../webshop/"
images_dir = "images"
javascripts_dir = "javascripts"
style.scss:
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}
li { display: inline-block; }
li { display: inline-block; }
a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}
#import "../webshop/_*";
_webshop-style.scss:
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}
li { display: inline-block; }
li { display: inline-block; }
a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}
div:hover {
padding: 12px 12px;
}

Sass will not attempt to remove any styling, ever, under any circumstance (only empty selectors and whitespace/comments are removed, depending on the chosen output style). Sass has no way of knowing if you are overriding previous declarations with a different selector (eg. .foo .bar and p.bar might match the same element), so it writes things out exactly as you specified.
If you want to continue writing/using duplicate declarations in your Sass, you will need to use a 3rd party tool (eg. linter) to remove them.

Related

Does anyone know where the error is in this CSS code?

I copied this code as an example of a nested ul and li inside a nav, but my vs code is showing me there is an error, can anyone point it out to me?
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
display: inline-block;
}
a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}
It is not valid CSS syntax, since CSS does not support nesting blocks like that. Your code is written in a CSS preprocessor syntax like SASS or LESS.
It is equivalent to this vanilla CSS code:
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav li {
display: inline-block;
}
nav a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
Your editor is probably complaining because you included this inside a file with the .css extension. It needs to be saved as .scss or .less depending on flavor and then you need a compiler to turn it into vanilla CSS.

Sass deduplicate #imports

I'm trying to create two themes for my project. I have following setup:
styles
globals
mixins
helper
themes
Now every theme has an index.scss:
#import "../../mixins/index";
#import "./colors";
#import "./breakpoints";
#import "./typography";
#import "core";
And every theme has a _core.scss:
#if import-once('core.scss') {
:global {
html, body {
background-color: $grey-page-background;
height: 100%;
}
body {
color: $grey-text-primary;
font-family: $font-family-standard;
}
body.page-body.modal-overflow-hidden {
overflow: hidden;
}
.container {
padding: 0;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
width: 100%;
#include breakpoint(large down) {
padding: 0 10px;
}
}
.no-margin {
margin: 0 !important;
}
.text-center {
text-align: center;
}
.green {
color: $green-smava-primary;
}
a:focus, a:hover, a:active {
color: inherit;
}
/* vb = vertical align block, for supporting browser dont support flex-box well */
.vb {
text-align: left;
}
.vb:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
}
/* vc = vertical align center child, for supporting browser dont support flex-box well */
.vc {
display: inline-block;
vertical-align: middle;
}
.ui.list {
list-style-type: none;
margin: 1em 0;
padding: 0;
.item {
table-layout: fixed;
list-style-type: none;
list-style-position: outside;
padding: .21428571em 0;
line-height: 1.14285714em;
}
}
.ui.list.large {
font-size: 1.14285714em;
}
}
}
As you can see -> index imports core -> and now the theme is imported to the according component (we have a versioning system for components - so this approach is good here).
So a component scss can look like this then:
#import '~styles/theme/smava/index';
.dialog {
&-input {
margin: 0 0 10px 0;
}
&-action {
border-top: 1px solid $grey-shadow-block;
float: right;
}
&-button {
&-pass {
margin-right: 30px;
}
&-login {
margin: 0;
}
}
}
Since I have multiple components core.scss gets imported multiple times.
The problem is, that I need to set a color for the body - this is the reason I have this core.scss.
So how can i deduplicate this? The approach with importing the theme has to stay the same unfortunately.
My stack:
React/Webpack/Redux/Node-sass

Is this CSS Syntax possible? [duplicate]

This question already has answers here:
Nested CSS styles?
(4 answers)
Closed 8 years ago.
So I was on Sass webpage learning a bit of its Syntax and saw a strange CSS Syntax that I don't know if it's posible.
Before asking I've already searched on W3School and other sites if that's posible.
Here is the code I found strange:
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}
li { display: inline-block; }
a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}
My question is if this Syntax is posible, I tried it and it doesn't work.
I also thought it can be a different language and searched but found nothing.
The normal Syntax I would do to make the code above work would be like this:
nav > ul {
margin: 0;
padding: 0;
list-style: none;
}
nav > ul > li {
display: inline-block;
}
nav > a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
SASS is a CSS preprocessor.
What is a preprocessor?
A preprocessor is a program that takes one type of data and converts it to another type of data.
It means that the code you've seen in SASS webpage isn't CSS syntax, it's SASS syntax, that is transformed in the latter after its preprocessor translates it.
The code you provided above would be transformed in something like this:
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav li {
display: inline-block;
}
nav a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
TL;DR
Before that style is added to a webpage, it's transformed into CSS. There's no stylesheet.sass references in an HTML page.

Show sub categories on Wordpress Sidebar using Two Level Menu Layout using wp_list_categories

I have a jsfiddle.net/vanduzled/AgAwK/ of what it turns out the output of wp_list_categories:
So I have A list of Category in wordpress with a sub category and I want it to display in my sidebar. I use wp_list_categories but what it displays is like this:
Accessories
Sub Accessory
Lifestyle Products
Sub Lifestyle Products
This looks good but I want to make the children (ie Sub Accessory) hidden and when you hover on the Parent (ie Accessories) the children will come out on the side like a normal vertical navigation with a Two Level Layout.
In my fiddle, the class .children is hidden and I put inline-block on when you hover on the parent but it doesn' work.
I'm actually using a Foundation Framework and Zurb has a Navigational Menu built in already but I can't use it in the dynamic insertion of menus as if to use a custom walker and then style is as necessary because in Foundation, they have an extra class which I cannot put in the wp_list_category function of wordpress.
I don't know if this can be done with pure css or a js will be necessary.
You can use a traditional css in doing this from A list Apart:
/* ASDIE NAV*/
ul.side-nav { display: block; list-style: none; margin: 0; padding: 17px 0; }
ul.side-nav li { display: block; list-style: none; }
.children{
width: 200px;
position: relative;
z-index: 1;
border-bottom: 1px solid #ccc;
}
ul.side-nav {
margin: 0;
padding: 0;
list-style: none;
width: 220px; /* Width of Menu Items */
border-bottom: 1px solid #ccc;
}
ul.side-nav li {
position: relative;
}
.side-nav li ul {
position: absolute;
left: 199px; /* Set 1px less than menu width */
top: 0;
display: none;
}
/* Styles for Menu Items */
ul.side-nav li a {
display: block;
text-decoration: none;
color: #777;
background: #fff; /* IE6 Bug */
padding: 5px;
border: 1px solid #ccc;
border-bottom: 0;
}
/* Fix IE. Hide from IE Mac \*/
* html ul li { float: left; height: 1%; }
* html ul li a { height: 1%; }
/* End */
ul.side-nav li a:hover { color: #E2144A; background: #f9f9f9; } /* Hover Styles */
li ul.side-nav li a { padding: 2px 5px; } /* Sub Menu Styles */
ul.side-nav li:hover ul.children, ul.side-nav li.over ul.children { display: block; } /* The magic */
/* ASIDE !NAV */

#import in #if statement in Sass

I want to load only the css needed for the login page for performance. On my other pages I want a grouped css file that will be cached on every page which contain all my css.
I have the following files:
minifiedcssforloginpage.scss
grouped-pages.scss
In minifiedcssforloginpage.scss I declare $load-complete-css:false. Afterwards I import myproject.scss which contains all the imports of my modules, layouts, core... In myproject.scss i want to do something like
#if $load-complete-css {
#import module1;
#import module2;
#import module3;
}
So minifiedcssforloginpage.scss would generate minifiedcssforloginpage.css with less css then grouped-pages.css (that has a var $load-complete-css set to true).
But I get an error that this is not possible "Import directives may not be used within control directives or mixins".
It's one of those things that's just not allowed. The only thing you can do is turn those imports into mixins (import the file outside the #if and call the mixin where appropriate).
Clarification:
_partial.scss
#mixin partial {
.test { color: red }
// other styles here
}
styles.scss
#import "partial";
#if $someval == true {
#include partial;
}
The core dev team is reluctant to implement this feature, although they are considering the implementation of a brand new dependency system.
See the following Github issues :
Allow #import within #if (#451)
Using #import statements within control directives or mixins (#779)
Allow optional #imports (#779)
Dynamic Dependencies (#739)
Put your styles into various partial files in a way that makes sense to you. Then, you can have create a separate SASS file for your login page that imports only the files with the relevant styles.
To quote from my answer to another question:
It is currently not possible to use SASS to include files dynamically.
#import cannot be used within control directives (e.g. #if) or
mixins, using a variable in an import directive is erroneous syntax,
and there is no directive for ending file execution early (which
effectively would allow conditional imports). However, you can
solve your issue by changing how you structure your style rules.
... If you have styles that [should be] conditionally included [they]
should be encapsulated in mixins, in 'module' or 'library' files. ...
The main idea is that importing one such file will not output any
css. This way, you can import these files redundantly so you can use
the mixins wherever you need them.
There isn't currently a way to place import statements within if blocks, unfortunately.
The closest alternative I'm aware of is to use the additionalData field to add a preprocessor function to your webpack sass-loader config:
{
loader: "sass-loader",
options: {
sassOptions: {
includePaths: [...],
},
additionalData: (content: string, loaderContext)=>{
// More info on available properties: https://webpack.js.org/api/loaders
const {resourcePath, rootContext} = loaderContext;
const finalPath = someCondition ? path1 : path2;
return content.replace(/SomeDynamicPathPlaceholder/g, finalPath);
},
},
},
More info on the additionalData field here: https://webpack.js.org/loaders/sass-loader/#additionaldata
I know this is a seriously old question, but we recently implemented this in our own tiny UI framework like this:
ui-framework/config.scss
$components: (
"component-a": true,
"component-b": false
) !default;
// A bunch of other default config
ui-framework/main.scss
#import "component-a";
#import "component-b";
ui-framework/component-a.scss
#if (map-get($components, "component-a") {
.component-a {
// Bunch of code here
}
}
ui-framework/component-b.scss
#if (map-get($components, "component-b") {
.component-b {
// Bunch of code here
}
}
And then in each project:
a-project/main.scss
// NOTE: We only want component b in this project
$components: (
"component-a": false,
"component-b": true
);
#import "ui-framework/config.scss";
#import "ui-frameowrk/main.scss";
We don't do this for every single component, but the huge ones that aren't always in use (like slideshow, dialog, form related code etc).
Old question, I know; just felt I'd provide an alternative scenario and expanded example based on something I was working on.
I ran into this issue because I was hoping to use one SCSS file for smaller screens and one for larger (top menu nav on desktop and burger menu for mobiles).
Using Blazor without Bootstrap, I was wanting to use the one menu structure in terms of the actual html and then use the SCSS to switch between the two at the relevant sizes. I'd created a SCSS file for the desktop version of the nav, and started on one for the mobile version. My plan, before I was aware of this stumbling block, was to selectively import the SCSS based on a media query in a mixin (aptly named mobileOrDesktop).
My idea was to use this mixin to do all the base structure manipulation for the media sizes. Something like this:
#mixin mobileOrDesktop {
#media (min-width: 961px) {
#import 'desktopNavbar.scss';
.container-fluid {
margin-top: 70px;
height: calc(100% - calc(60px + 70px));
}
//show the footer, maybe tweak the font size, etc
}
#media (max-width:960px) {
#import 'moblieNavbar.scss';
.container-fluid {
height: 100%;
}
//hide the footer, maybe tweak font sizes, etc
}
}
Unfortunately, we can't do that due to how SCSS works. So, rather than just dumping all the CSS in the media query (I wanted to keep it relatively split up so that it was more manageable for debug/altering), I had a hunt for alternatives.
Similarly to Cinnamon, I found the most viable solution to be importing the SCSS outside of the mixin and simply including it within the mixin:
#import 'desktopNavbar.scss';
#import 'mobileNavbar.scss';
#mixin mobileOrDesktop {
#media (min-width: 961px) {
#include desktopNavbar;
.container-fluid {
margin-top: 70px;
height: calc(100% - calc(60px + 70px));
}
}
#media (max-width:960px) {
#include moblieNavbar;
.container-fluid {
height: 100%;
}
}
}
With the imported SCSS files being a mixin themselves, i.e. the desktopNavbar.scss becomes:
#import 'siteVariables.scss';
#mixin desktopNavbar {
#navbar {
.burgerIcon {
display: none;
}
.nav {
overflow: hidden;
background-color: $navy;
vertical-align: middle;
height: 70px;
line-height: 70px;
color: $blizzard;
position: fixed;
top: 0;
width: 100%;
display: block;
z-index: 99999999;
.leftBlock, .midBlock, .rightBlock {
display: inline-block;
vertical-align: middle;
height: 70px;
padding: 0px;
margin: 0px;
line-height: 70px;
}
.leftBlock {
width: 20%;
.imgLogo {
margin-left: 10px;
margin-top: 5px;
max-width: 120px;
}
}
.midBlock {
width: 60%;
text-align: center;
.navbar-nav {
display: inline-flex;
flex-wrap: nowrap;
flex-grow: 2;
flex-shrink: 2;
list-style: none;
vertical-align: middle;
margin: 0px;
padding: 0px;
.nav-item {
max-width: 175px;
color: $white;
display: inline-block;
vertical-align: middle;
height: 70px;
.btn-link {
font-size: 16px;
text-align: right;
color: $white;
padding: 14px;
line-height: 20px;
text-decoration: none;
vertical-align: middle;
span {
font-family: 'Font Awesome Solid';
line-height: 60px;
height: 60px;
vertical-align: middle;
padding: 5px;
}
}
&.dropdown {
font-size: 16px;
text-align: right;
line-height: 20px;
text-decoration: none;
vertical-align: middle;
.dropbtn {
font-size: 16px;
text-align: right;
line-height: 20px;
text-decoration: none;
vertical-align: middle;
span {
font-family: 'Font Awesome Solid';
line-height: 60px;
height: 60px;
vertical-align: middle;
padding: 5px;
}
}
.dropdown-content {
display: none;
position: fixed;
top: 68px;
text-align: center;
background-color: $star-command;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 99999999999;
.dropdown-header {
color: $blizzard;
}
.dropdown-item {
color: $powder;
padding: 12px 16px;
text-decoration: none;
display: block;
&:hover {
background-color: $blizzard;
color: $navy;
}
}
}
&:hover {
background-color: $star-command;
.dropdown-content {
display: block;
}
}
}
}
}
}
.rightBlock {
width: 20%;
}
}
}
}
And the site SCSS can simply be:
#import '../../FontAwesome/scss/fontawesome.scss';
#import '../../FontAwesome/scss/regular.scss';
#import '../../FontAwesome/scss/solid.scss';
#import 'siteVariables.scss';
#import 'mixins.scss';
//import other stuff here
html, body {
height: 100%;
overflow: hidden;
width: 100%;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif !important;
margin: 0px;
#include mobileOrDesktop;
.container-fluid {
overflow: auto;
main {
padding: 15px;
}
}
#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
.dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
}
}

Resources