I want to write a single rule for all browser pseudo-elements in type=range input separated by commas, but realised it's not working in my case
//this works
input[type="range"] {
&::-webkit-slider-runnable-track {
height: 2px;
}
}
//this doesn't
input[type="range"] {
&::-webkit-slider-runnable-track, &::-ms-track, &::-moz-range-track {
height: 2px;
}
}
Googling shows that some applications of this work like here Simplified SASS selectors for child pseudo elements?
But maybe the case is in my sass version, or I can't use it with this kind of pseudos?
Related
I want to apply a number of CSS rules to different selectors, without creating additional selectors. In SCSS, this would be typically done with a mixin, eg:
#mixin gradient-text {
color: transparent;
background-clip: text;
-webkit-background-clip: text;
background-image: linear-gradient(
350deg,
var(--dark-blue),
var(--teal),
var(--bright-green)
);
}
Reading around the internet, there's lots of references to making mixins with the CSS apply syntax, but
https://caniuse.com/sr_css-apply mentions:
#apply was briefly supported behind a flag in Chromium but has since been abandoned in favor of the ::part() selector.
Reading about CSS part though it seems like it's not possible to use CSS part without modifying my HTML and using web components, which have their own issues.
Is it possible to do a mixin in CSS, without modifying my HTML or JS, using part?
According to the MDN article you linked to, ::part can only match elements within a shadow tree. Additionally, the spec for the ::part states
The ::part() pseudo-element only matches anything when the originating element is a shadow host.
Thus, if you wanted to leverage this pseudo-element for CSS mixins, you'd be better working with (developing) a native web component library. You may be able to use the corresponding part HTML attribute outside of the Shadow DOM to implement CSS mixins depending on your requirements.
When in doubt the best thing is to experiment. Here is an example of using ::part() and part (HTML attr) inside and outside of a shadow DOM. Best to test browser support on part as it is a relatively new technology. Moreover, seems there is still ongoing questions about how multiple ident's should be supported, if at all.
customElements.define('custom-thing', class CustomThing extends HTMLElement {
constructor() {
super()
const root = this.attachShadow({ mode: 'closed'})
root.append(document.getElementById('custom').content.cloneNode(true))
}
})
[part~="a"] {
color: red;
}
[part~="b"] {
padding: 20px;
background: gray;
}
p::part(a) {
color: blue !important;
}
custom-thing::part(a) {
color: green;
}
custom-thing::part(a)::after {
content: 'A';
}
custom-thing::part(b) {
color: orange;
}
custom-thing::part(a b) {
/* does multiple ident values work? */
color: blue;
}
<p part="a b">part</p>
<template id="custom">
<style>
p[part="a"] {
color: aqua;
}
</style>
<p part="a">part a</p>
<p part="b">part b</p>
<p part="a b">part a b</p>
</template>
<custom-thing></custom-thing>
I'm trying to slightly modify the styles of a block formatting plugin in Wordpress by overriding them in my own theme stylesheet. I use Sass but I'm new to it.
Pasting all of the selectors right out of Developer Tools works, but I know that's not the elegant/modular way to do it:
.an-accordion.an-accordion--v2.an-accordion.an-accordion--design-basic .an-accordion__heading {
color: gold
}
What's the right way to do this in Sass? I've tried something like this:
.an-accordion {
&--v2 {
&--design-basic {
&__heading {
color: gold;
}
}
}
}
but it doesn't work. I can tell I'm missing something about the way .an-accordion repeats.
You can use the power of local scoped string variables $something:... combined with the power of string interpolation #{...} and combine it with the current selector string & to create a compound selector for any combination of block, element, and modifier. Which I think is quite nice and readable:
.an-accordion {
$modifier-v2: #{&}--v2;
$modifier-design-basic: #{&}--design-basic;
$element-heading: #{&}__heading;
&#{$modifier-v2}#{$modifier-design-basic} {
#{$element-heading} {
color: gold;
}
}
}
which will result in:
.an-accordion.an-accordion--v2.an-accordion--design-basic .an-accordion__heading {
color: gold;
}
I tried it out on sassmeister.com
Note that I omitted the duplicated .an-accordion class in the selector; if this is important for you to increase the specifity you can insert it with #{&}.
BEM is about blocks, elements, and modifiers. Block scope is the biggest one, the element is some part inside the block and the modifier is optional and represents the status of your block-element. In Sass you can nest elements if they are parent and children and you don't need to repeat the parent element, in your stlesheet, if the beginning of your property is the same for both parent and child, but if the beginning is different you must repeat.
In a html like this:
<div class=" an-accordion an-accordion--v2 .an-accordion--design-basic .an-accordion__heading"></div>
You could have some scss code like this:
.an-accordion{
color: #000;
&__heading{
background-color: tomato;
}
&--v2{
font-weight: bold;
}
&--design-basic{
border: none;
}
}
I see some e.g. div/button style in Chrome console like this:
/* Chrome browser styles tab */
.ItemClass1-0-3-171.ItemClass2-0-3-173: {
background-color: "red"
}
How do I define a new style in CSS ignoring that class numbers? because it can be a different number for other div/button on the page..
/* CSS file */
.ItemClass1.ItemClass2 {
background-color: "blue"
}
You can use two attribute contains selectors for this.
[class*="ItemClass1"][class*="ItemClass2"] {
background-color: red;
}
<p class="ItemClass1-0-3-171 ItemClass2-0-3-173">foo</p>
But keep in mind that this will also select elements with the class fooItemClass2.
You can use an attribute selector with a starts-with value to pick up anything that starts with ItemClass.
Note: This solution assumes ItemClass is the first classname and doesn't account for whether the element has both classes. For these reasons Sven's answer might better suit your needs.
[class^='ItemClass'] {
background-color: blue;
padding: 4rem;
}
<div class="ItemClass1-0-3-171.ItemClass2-0-3-173"></div>
Are there any tools to compile CSS custom properties declared at not :root rule? I want following code with custom properties
.dark {
--bg-color: black;
--fg-color: white;
}
.light {
--bg-color: white;
--fg-color: black;
}
.foo {
background: var(--bg-color);
display: block;
}
.bar {
color: var(--fg-color);
display: inline;
}
be compiled to their non-custom-prop equivalents like that
.light .foo, .light.foo {
background: white;
}
.dark .foo, .dark.foo {
background: black;
}
.light .bar, .light.bar {
color: black;
}
.dark .bar, .dark.bar {
color: white;
}
.foo {
display: block;
}
.bar {
display: inline;
}
The goal is to
switch color schemes by switching dark/light class on root DOM element
use valid css syntax (no sass less)
keep rules code compact
It's actually not safe to do that. I can tell you because I tried so hard to make a safe transformation.
But I failed.
https://github.com/postcss/postcss-custom-properties/issues/1
Ideal solution. Your example is valid CSS and can be used in many browsers (not in IE, Edge (but is in development) and Opera Mini as of writing this answer, 2017-03-27, other major browsers are fine).
Suboptimal solution. Some CSS can be transpiled to achieve better browser support. The solution I found does not support variables on non-:root elements, however. There are also other objections against transpiling of 'future' CSS into 'current' CSS. To the best of my knowledge, you will have to implement your own transpiler (or postcss plugin) if you want to transpile custom properties not on the :root element, but be warned that that is hard in general. Now you don't need the general part, so it is possible. Just does, to the best of my knowledge, not exist yet.
Preprocessing solution. Of course, you don't need a general implementation of custom properties. You have different themes that have their own values for the same set of properties and that's it. Thus, a separate stylesheet can be created as a preprocessing step using any CSS preprocessor.
Now you say the following,
use valid css syntax (no sass less)
but I am going to show this anyway, because I believe that it is a valid solution to your problem. It is definitely the only one I know that actually works if you want to/need to support IE, Edge and/or older versions of other major browsers (Firefox < 31, Chrome < 49, Safari < 9.1, Opera < 36)
You could do this using SASS for example, to do the transpiling on the server side.
// define styles, use variables throughout them
// your entire style definition goes into this mixin
#mixin myStyles($fg-color, $bg-color) {
.foo {
display: block;
background: $bg-color;
}
.bar {
display: inline;
color: $fg-color;
}
}
// define themes, that set variables for the above styles
// use named arguments for clarity
.dark {
#include myStyles(
$fg-color: white,
$bg-color: black
);
}
.light {
#include myStyles(
$fg-color: black,
$bg-color: white
);
}
This compiles to the following.
.dark .foo {
display: block;
background: black;
}
.dark .bar {
display: inline;
color: white;
}
.light .foo {
display: block;
background: white;
}
.light .bar {
display: inline;
color: black;
}
This is not exactly what you want to obtain, but very close. Realistically, I think this is the closest you will get to obtaining your desired output. I know you want to
keep rules code compact
but what you are saying there (I think) is that you want to split out custom properties from their rules to save on number of rules, which is not something any preprocessor I know supports.
You can organize your source SASS in separate files to keep an overview easily. You can even set up a build system that generates a separate stylesheet for every theme you have. It is then possible to have your users select an alternative stylesheet. Browsers have some support for this, but switching using JavaScript is also definitely possible in the latter case. Simply set all stylesheets to be disabled except for the selected one. Here is an example.
How can we know if any website is using Sass and Compass for CSS?
That's a though one, but I would take a look at the CSS files, IF the developers forgot about changing the output, you'll be able to spot the file names and line numbers of the source files.
If not, look for uncommon patterns in the CSS output, for instance SASS makes nesting very easy to do, so a selector could look like this in the CSS (you would never hand-write this long selectors)
div#wrapper div#container ul#myId li a { color: blue; }
div#wrapper div#container ul#myId li.sass a { color: red; }
But would be look like this in SASS source file (no repetition, easy to getaway with)
div#wrapper {
div#container {
ul#myId {
li {
a { color: blue; }
&.sass {
a { color: red; }
}
}
}
}
}
Also, look for lengthy class combinations, those come from using the #extend directive, that would look like this:
.button, .button1, .button-submit, .button-add-to-cart, .button-signup, .button-register {
display: inline-block;
}
Another good idea is to look in the source of CSS3 generated buttons, usually developers only care for Firefox, Safari, Chrome and IE, but a SASS generated output will be REALLY verbose with a lot of vendor prefixes, including ones for Opera.
Good luck!
if the developer forgot to compile for production or minify the .css, than you should still be able to see the automatically inserted comments that point back to the original source, like:
/* line 22, ../../../../../Ruby193/lib/ruby/gems/1.9.1/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
.selector {
bla: 123;
}
or
/* line 5, sass/large/_common.scss */
.selector {
bla: 123;
}