Duplicate CSS rule out put when using attribute selector containing slashes and colon - sass

I've got a pretty basic selector that contains some slashes and a colon:
[data-sitemap-state="/register/:/"] {
#include typography;
}
I've using gulp-sass, which as far as I know uses node-sass, and therefore lib-sass under the hood.
The mixin (typography) looks like this:
#mixin typography {
font-weight: 700;
font-size: 1.25em;
}
When the SCSS is built the following CSS is generated:
[data-sitemap-state="/register/:/"],
[data-sitemap-state="/register/.\:/"] {
font-weight: 700;
font-size: 1.25em;
}
I don't understand why the additional selector is generated:
[data-sitemap-state="/register/.\:/"]
Particularly .\:/
I've tried escaping the colon character and using the unicode/hex values for the colon and the same CSS is generated regardless.
I was expecting this output:
[data-sitemap-state="/register/:/"] {
font-weight: 700;
font-size: 1.25em;
}

It's possible this additional rule is created for IE8 support.

Related

Svelte giving warning for additional class selector on :global()

I am using SCSS in my sveltekit +layout.svelte file to create a global stylesheet. I couldn't find a built-in way to make a global stylesheet so I resorted to just using :global(). This is the code I used:
:global(:where(p, .content)) {
$size: 1rem;
&:not(:last-child) {
margin-block-end: #{$line-height}rem;
}
&.dropcap::first-letter {
$line-count: 2;
font-size: calc($size * (1 + ($line-count * $line-height)));
float: left;
line-height: 0;
vertical-align: middle;
clear: both;
}
}
(note: :where() is used because :global() doesn't support multiple selectors)
The first rule of &:not works fine, but the second rule of &.dropcap shows a warning in the terminal of unused selector (the only content that will match it would go in the <slot /> of layout) and it gets removed from the css output. When I use &:global(.dropcap) svelte also includes the second :global() in the css output. How do I make svelte not remove the css?
The :global() might not propagate inward, you may have to add it everywhere.
For global stylesheets it usually is easier to import them in the <script> along the lines of:
import '../styles/sheet.scss';
This requires the build to be set up to handle such imports, SvelteKit uses Vite which should be able to do this by default.
For some reason, wrapping the problematic selector with :where made the warning goes away (and works).
:global(:where(p, .content)) {
$size: 1rem;
&:not(:last-child) {
margin-block-end: #{$line-height}rem;
}
&:where(.dropcap::first-letter) {
$line-count: 2;
font-size: calc($size * (1 + ($line-count * $line-height)));
float: left;
line-height: 0;
vertical-align: middle;
clear: both;
}
}

Stylelint: Expected declaration to come before rule - order/order

The code is as follows:
.home-feat2 {
background-color: stencilColor("color-greyLight");
img {width: 10rem;}
margin-bottom: spacing("single");
#include breakpoint("medium") {
margin-bottom: 3rem;
}
}
Expected declaration to come before rule - order/order points to the line with margin-bottom: spacing("single"); however I tried looking up what this error meant but I can't find a lot of descriptive documentation on stylelint. Maybe it's because I just don't understand the terminology, but I'm having trouble finding anything on this subject. Any help is appreciated.
Your linters expects you to write declarations before rules.
In CSS, a declaration is the key-value pair of a CSS property and its value, like margin-bottom: spacing("single").
See a visual representation of a declaration block.
A rule is the block defined by one or multiple selectors, containing declarations, like: img { width: 10rem; }.
See a visual representation of a rule set.
What it means for you, it means that you should probably write the rule img {} after the declarations:
.home-feat2 {
background-color: stencilColor("color-greyLight");
margin-bottom: spacing("single");
#include breakpoint("medium") {
margin-bottom: 3rem;
}
img {width: 10rem;}
}
This specific rule purpose is to allow an easy to read code.
When applied, you can see at the first glance that background-color and margin-bottom are applied to .home-feat2 and width is applied to img.
edit: added some additional informations thanks to jeddy3

gulp-clean-css cleaning / removing duplicated css when using #extend

I'm having a weird problem with #extend on scss. when i extend some %placeholder that have repetitive properties, the gulp-clean-css merge them, and I don't want that to happen.
Here's an example:
foo.scss
%one {
font-size: 16px;
width: 95%;
}
%two {
font-size: 1rem;
width: calc(100% - 10px);
}
.foo {
#extend %one;
#extend %two;
}
.foo2 {
font-size: 16px;
font-size: 1rem;
}
foo.min.css
.foo{font-size:1rem;width:calc(100% - 10px);}
.foo2{font-size:16px;font-size:1rem}
Why does this happen?
If it helps, this is mine gulp-task:
gulp.task('scss', function(){
console.log('start task scss');
gulp.src(folderStyles)
.pipe(sass.sync().on('error', sass.logError))
.pipe(rename({ suffix: '.min' }))
.pipe(cleanCSS({compatibility: 'ie9', noAdvanced: true}))
.pipe(gulp.dest(folderStyles));
logEnv();
});
Is there any other better plugin to use?
I don't want it to remove duplicated properties. If you ask me why, it's because of old browsers support than might not support rem or calc, or other "new fancy propertie" ;)
Thank you :)
I played around with this, and I think your setting is incorrect for 'noAdvanced':
Instead of:
.pipe(cleanCSS({compatibility: 'ie9', noAdvanced: true}))
Use:
.pipe(cleanCSS({compatibility: 'ie9', advanced: false}))
According to the docs:
advanced - set to false to disable advanced optimizations - selector &
property merging, reduction, etc.
https://github.com/jakubpawlowicz/clean-css#how-to-use-clean-css-api
This isn't going to leave you with 1 .foo selector with two font-size declarations tho, it's just not going to merge the two, so you'll end up having:
.foo {
font-size:16px;
width:95%
}
.foo {
font-size:1rem;
width:calc(100% - 10px)
}
.foo2{
font-size:16px;
font-size:1rem
}
This answers your issue however kind of defeats the purpose of using something like clean-css. I'm curious as to why you would want to leave both font-size declarations in your CSS when the first one will be overridden anyway.

compiling sass with grunt produce invalid property name

I don't know why but while compiling with grunt or anything there is an error called invalid property name
#flotTip {
border: none !important;
font-size: $font-size-small !important;
line-height: 1px !important;
#extend .tooltip-inner() !important;
}
in the above code in the line-height it produces an undefined property. My task was to convert all less files into sass files. Used many solutions to convert all of them to sass as far as I can find. But this one I can't find any solution. Can anyone answer what might be the problem?
Extend is only for extending simple selectors, like class, element, or id. You cannot use !important with #extend. This is the correct way to use extend:
.foo {
color: red;
}
#flotTip {
#extend .foo;
}
You may be confused confusing extends with mixins, which also cannot use !important. This is the correct way to use mixins:
#mixin foo() {
color: red;
}
#flotTip {
#include foo();
}
The line-height: 1px !important; line looks fine. The problem is with the following line. If you're trying to include a mixin, use #include and don't prefix the mixin's name with . (dot). Also, don't put !important after it.
I would guess that you are using #extend incorrectly. See the docs here: http://sass-lang.com/documentation/file.SASS_REFERENCE.html#how_it_works

How to use !important keyword in a mixin?

I can't get Sass to output the !important keyword with a mixin, I've tried:
#include font-size($font-size-sml) !important;
And:
#include font-size($font-size-sml !important);
It always throws an error.
EDIT
I ended up with this which works fine:
#mixin font-size($font-size, $sledge-hammer: "") {
font-size: $font-size #{$sledge-hammer};
font-size: ($font-size / $base-font-size)+rem #{$sledge-hammer};
line-height: ceil($font-size / $base-line-height) * ($base-line-height / $font-size);
}
You can't add !important to whole mixin in SASS (It is possible in LESS I think) like you're trying to do in first example.
Second example works for me (you can pass !important with a parameter), I mean, if you use $font-size-sml directly as a property value it works, so maybe check your syntax.
But if it's really not working for you, you can do something with flag, set a important_flag as a mixin parameter and then use if-else statement in mixin. Something like this:
#mixin large-text($prop, $is_imp: false) {
#if $is_imp == false {
font-size: $prop;
} #else {
font-size: $prop !important;
}
}
Maybe it's not a glamorous way to do it, but it works ;-)
You can use the if(condition, when-true, when-false) function.
So the code will be simplest and compact:
#mixin large-text($size, $isImportant: false) {
font-size: $size if($isImportant, !important, null);
}

Resources