Two stylesheets targeting the same element with equal specificity, which takes precedence? - css

I have two stylesheets built from the same .scss files that only differ in a few places. One is a master with all styles and the other is missing a few pieces here and there. These need to coexist, they each have a specific use case and are intended to be downloaded by the user. Because webpack won't bundle CSS on its own, I have to import both of these stylesheets which means they can potentially affect my site.
My index.js is along the lines of
import "./master.scss";
import "./specific-case.scss";
My webpack.config.js is along the lines of
module.exports = {
...
...
plugins: [
specificCaseExtraction,
masterExtraction,
...
I'd like the whole application to use master.scss styles, but there are a few places where spceific-case.scss is stepping in an messing up the styling, despite them using the same source (precedence is pretty well defined with the sheets themselves, but they don't play well together which only a problem in this demo application and will never be the case when used properly).
Basically, my question boils down to this: Is there a way to ensure that one stylesheet takes precedence over another? Is it a matter of ordering? I tried swapping them in index.js but it didn't help, and swapping them in webpack.config.js is a bit more complicated because the masterExtraction is called manually while the specificCaseExtraction is actually one of many that is injected dynamically. Or, better yet, is there a way to have webpack compile and package .scss into .css without having the inject it into the page itself?
UPDATE:
Turns out that in times of equal specificity, the style that's further down the sheet is the one that takes effect. That means that reversing the order of the plugins in the list made the master.css appear below the specific-case.css in the final index.html which means that the master styles always take precedence over any others and my problem is solved.

CSS specificity is in order of precedence.
This is the best article I have seen by far: https://css-tricks.com/specifics-on-css-specificity/
Here is a similar project using LESS instead of SASS but the concept is the same.
https://github.com/mabbashm110/Sprint-Challenge--Responsive-Less
Hope that helps.

Related

Is it possible to disable automatic line breaks on Sass's CSS output?

I very frequently use the CSS line numbers in Inspect Element to find where a rule is in a particular CSS file. When Sass outputs a CSS file, it imposes its own style rules on it which really don't line up 1:1 with how my SCSS is formatted. This makes it hard to find CSS rules in my code because none of the line numbers match. It's completely disturbing my workflow and is a major barrier to my further adoption of Sass.
I've already looked at sass --style=expanded and sass --style=compressed but neither of them come anywhere close to matching the whitespace style I want.
What I really need is a way to make Dart leave all my whitespace and line breaks exactly as they are, and minify mixins down to a single line each. Something you might call --style=preserve-line-numbers Is it possible?
No. That is not possible by SASS itself.
If you like you may have a look to the avaiable styles:
https://sass-lang.com/documentation/js-api#outputstyle
But to be honest: if you use SASS in the intended way with nested styles, mixins, using modules ... the compiled CSS will considerably differ from the SASS code anyway. That even applys to the line numbers. So your problem is a common challenge in the coding process.
As fast debugging is important SASS offers mapping technique:
If activated you are able to see the source code in the browser on the fly. That's really easy and should meet your demands. Maybe you like to have a look on it. Here is a good overview to it: https://thesassway.com/using-source-maps-with-sass-3-3/
Or however if not that way there is another little trick/workarround which may help:
Most SASS projects organize/structures code in partial files (which doesn't make it possible to keep line numbers). That's for different reasons and speeds up working as well. If you do so you just start every file with a CSS comment which notes the file name only. As comments are shown in the browser tools you are able to find the relevant SASS source file without mapping ... and as partial files are almost not as long finding the relevant code (which differs from the CSS) should not longer be the problem.
// ### examples partial filename in a CSS comment
/* base-typography */
...
/* base-forms */
...
/* section-hero */
...
That is not as fast as mapping technique I would really recommend. But finding the code that way is faster than try to keep line numbers exactly the same and missing that way a lot of other advantages of SASS which speeds up my work (like nestings, setting SASS only comments, using mixins and modules ...).

How to import SASS stylesheet and apply them only to a particular element?

I have the following code
#import '~bulma'
In Webpack this means that I’m just importing whatever SASS the #import statement points to. In this case, it’s a pretty deep set of styles.
I would like to apply this only to the children of a particular container:
<div class="apply-bulma-here">...</div>
The children can be arbitrarily complex.
The first thing I tried is this:
.apply-bulma-here >
#import '~bulma'
This seems to work on simple JSFiddles but in my code it doesn’t seem to work completely. I suspect that after some depth in the SASS files the styles aren’t picked up anymore.
Is this the right approach? Is there a quick way to scope the import only to the descendants of one particular element?
By looking at the compile code it seems that every single rule is prefixed with the additional condition .apply-bulma-here> which sounds about right. So I don’t understand why it would behave differently.

Importing & Extending raw CSS?

I have a preprocessor import problem. I have vendor css that i would like to copy functionality. Unfortunately, i don't control the html for this situation either.. so essentially i have vendor css & different vendor html, and i am trying to extend functionality of one css rule into another.
Now, the basic concept in many css preprocessors is to extend the rule.
// Vendor
.foo { font-weight: bold; }
.bar { text-color: red; }
// Mine
.bar { .foo }
In the above example, you don't have access to .foo or .bar, but with preprocessors, you can extend functionality from .foo into .bar, which works great for less/stylus/etc. The problem, is when the vendor rules are only defined in raw css.
So with that said, the most obvious solution is to have Stylus/Less import the raw css as stylus/less. However, neither seem to be able to actually do this.. that i've found at least. Less doesn't seem able to (#import "foo.css" directives are ignored) and while Stylus has an option to actually include the imported raw CSS, it did not seem to actually be processing it. That is to say, it would include the css, but #extend directives failed (perhaps i am wrong?).
The other option i could think of is simply renaming the .css files to the preprocessor language extension. Since we want to keep the vendor stuff out of our hands, allowing for proper versioning/etc, This involves a build process which copies the target css files and renames them into the target language extension, but this is error prone. Stylus ran into syntax errors immediately, and Less could just as easily (as not all CSS is valid Less. most is, but not all).
So.. any additional thoughts on this front? Hopefully there is an option i may be missing? Perhaps SCSS handles this better?
Currently, with what i have found is/isn't possible.. i feel the only stable way is to simply copy the raw css bits into my css code. If the vendor code changes, i'll have to update manually, but at least i don't run the risk of vendor stuff changing and all of a sudden the build process fails, because vendor introduced some CSS syntax not supported by less/etc. It is far from good.. but the worst that can happen is my css looks funny, and i need to update.
edit:
I'm going to try SCSS next.. we'll see how it goes. On the site, they claim all CSS(3 only?) syntax is valid SCSS
edit2: For clarity. My question is, give the above scenario, what would you do? Importing the .css files is not possible (See note below!), and renaming .css files to .less/.stylus can in turn be error prone, since less is not a perfect superset of CSS(namely due to proprietary features).
!Note!: I have since been digging around the less source to see what could be done to fix this problem, rather than work around it, and ran into a dozen support tickets on the matter. The main discussion of which seems to be taking place on #issue 1185, and more importantly, check out the changelog which *(i believe) addresses this issue! CHANGELOG 1.4.0 Beta
So with that said, the #import (less) "file.css" is likely the winning scenario here, even if it may have a few bugs due to the beta status. Yay :)
Your best bet is either what #Lee Olayvar said, or use the new ":extend()" feature in LESS. It sounds like you might have tried the extend feature, but you used the "SASS directive" syntax (which IMO is improper use of an at-rule), whereas LESS uses the CSS-like pseudo-selector syntax:
.foo:extend(.bar) {}
And if you are patient (in the coming days/weeks), you will see a new feature that is perfect for what you want to do, and it's unique to LESS. It will allow you to extend or mixin external "silent" styles. Meaning you will be able to "#import" and external stylesheet but the styles won't show up in your compiled code unless you extend them or use them as a mixin.
I'm on the core team for Less.js btw, so let me know if you have any other questions or if I can be of further help.
It looks like all imported .css files won't be prepocessed by less but will just be added with an #import at the top.
You can import both CSS and LESS files. Only LESS files import statements are processed, CSS file import statements are kept as they are. If you want to import a CSS file, and don’t want LESS to process it, just use the .css extension
Source: http://lesscss.org/
The best thing you could do would be the renaming I believe.
While still in beta, the newly added #import (less) "file.css" syntax should properly handle all CSS files. Due to the "official" support, it can also be expected/assumed that any proprietary syntax that breaks LESS would be fixed (though possibly not "supported").
So in theory this is the best option! Barring SCSS, which i have not tried yet in this scenario. Stylus still has issues though, in my tests.
For more information, check out this issue or this changelog.

Are there reasons to still use the "#import" css rule?

I recently came across a use of the #import rule on Coda.com. They're actually using to import the main style sheet for the site, specifically the format:
<style type="text/css" media="screen">
#import url(./coda.css);
</style>
Which will hide the rules from Netscape 3 and IE 3 and 4. Since a web development tools primary audience will be using modern browsers, what other reasons would there be to use this rather then a link?
None. Using a <link> element also has the advantage of getting rid of the FOUC.
EDIT: Using #import in another stylesheet (.css file) can be used like an #include in C, but there isn't any reason to use #import in a <style> block.
For Coda's site, I'd imagine they did that more out of force of habit rather than any pressing technical need.
#import statements inside of actual CSS files (not in a <style> element in HTML) serve many purposes, such as making it easy to swap in and out other CSS files. The Blueprint CSS framework does this to let you easily remove certain portions of the framework such as the typography stuff or the grid stuff.
Of course, in a production environment, using a bunch of #import statements is frowned down upon because it increases the number of files a web browser has to pull down.
The only reason to use this rule today is to make your CSS more modular by splitting it into different files, like libraries.
So, while your page might link to one stylesheet, that stylesheet can #import other stylesheets for reset, typography, etc.
However, this does slow the loading of your page since it's just more sequential http requests.
I agree with Andrew. I also use imports to split out my css logically. Personally I like to split them out in 4: reset, structure, typography, general (bgs/borders etc)
Depending on the person doing it, their style and preference, css files can also be split out by page section eg header.css, footer.css etc.
One extra thing I do however to avoid the multiple http requests is have a build process which merges (in order of import) and compresses the css files for live deployment.
Hope this helps
I use a modular development approach myself, and often end up with 10+ individual CSS files. As you know, that's a pretty drastic number of HTTP requests, so I like to use Blender.
Blender is a rubygem that consolidates and minifies any number of CSS files into a single stylesheet. It also works for JavaScript.
You can define #media in your individual stylesheets to only serve the appropriate rules to the correct device types.

What is the point of #import?

Can someone explain what are the benefits of using the #import syntax comparing to just including css using the standard link method?
As the answerer said, it lets you split your CSS into multiple files whilst only linking to one in the browser.
That said, it's still wasteful to have multiple CSS files downloading on high-traffic websites. Our build script actually "compiles" our CSS when building in release mode by doing the following:
All CSS files are minified (extra whitespace and comments removed)
We have a "core.css" file that's just a list of #import statements; during compilation, each of these is replaced by the minified CSS of that file
Thus we end up with a single, minified CSS file in production, whilst in development mode we have the separate files to make debugging easier.
If you use <link>s in your HTML files, all those files have to keep track of all the CSS files. This obviously makes changes and additions (both for CSS and HTML files) harder.
Using #import, you reduce a theoretically infinite number of changes down to one.
#import allows you have an extensible styesheet without having to change the html. You can link once to your main sheet and then if you want to add or remove additional sheets your html doesn't change.
Also, more smaller files help the browser do better caching. If you make a change in one part of a large sheet, the entire sheet must be downloaded again for every user. If the styles are separated into logical areas among a few sheets, only the file containing the part that changed needs to be downloaded. Of course, this comes at the cost of additional http requests.
One other handy bit, although pretty outdated, is that Netscape 4 couldn't handle #import, so it is a good way of serving a stylesheet to NS4, then having another stylesheet for more modern browsers that was imported in a standards compliant way.
#import is CSS code. <link> is HTML code. So, if you want to include stylesheets in other stylesheets (or if you can’t change HTML), #import is the way to go.
According to the CSS spec, all #import declarations must appear before any style rules in your stylesheet. In other words, all at the top of your stylesheet
Any #import declarations that appear after style rules should be ignored. Internet Explorer has never respected this; I believe other browsers do. This makes #import a bit less useful, because rules in a stylesheet that’s imported will be overriden by rules of equal specificity in the importing stylesheet.
It allows you to keep your logic CSS file spread over multiple physical files. Helps in team development, for example. Also useful when you have a lot of CSS files that you want to separate by functional areas (one for grids, one for lists, etc), let have accessible in the same logical file.
Say you work for Massive Dynamics, Corp.. It has a Widgets division. The Widgets division has an Accounts department. Accounts is divided into Accounts Payable and Accounts Receivable.
Using #include, you start the website with one top-level global.css stylesheet, which applies to everything.
Then you create a second stylesheet, widgets.css for the Widgets division. It #includes the global one, and its own styles (which can over-ride the global styles if needed, because of the Cascade). Then you create a third accounts.css for Accounts. It #includes widgets.css, which means it also includes global.css. Lather, rinse, repeat.

Resources