Very good demo on how to utilise this. I’ve been doing this for a while and a big win is coming back over time and making changes. So much easier to understand. I end up with three groups per component. ( - Private custom props with corosponding registered properties - Rules with the private props - modifier that set the registered properties.
It's ok to define a color pallete with variables, but I definitely recommend defining a semantic palette on top of that for components to use. The semantic palette can be assigned at runtime for different color schemes (high contrast, dark mode, etc), and components don't need to know anything about the actual colors.
@@collimarco not the original commenter but this is how I do it: I have two level of variables: synonyms and semantics; synonyms are things like "--cl-red: #f71010" (as per the client's brand manual), while semantics are like "--cl-danger: var(--cl-red)". In some places, I'd use "--cl-red" because the element is simply red, in others I'd use "--cl-danger" because the element performs a dangerous operation. This way, I can later redefine it as "--cl-danger: var(--cl-orange)" on darker themes, and all the dangerous elements would turn orange, while the elements that are red for aesthetic reasons wouldn't change. This could be applied for the whole theme, with the semantics changing while the synonyms stay the same, because they were lifted straight from the client's visual guidelines.
Exactly. Use color variables that are meaningful to their purpose, not the actual hex/rgb value. Then those meaningful color variables can be assigned different values based on any criteria we want without requiring all the components in the design system to change.
Establishing that set of meaningful variables requires a bit of thought - usually a lot of discussion with designer. One would hope the design system doesn't end up with 30 different variables for different backgrounds. Typically designers would refer to those in their specs.
I have learned this technique from your css demstified course and I really like it and I love the fact that you are making it on TH-cam also and to see how you also evolved in thinking from that point You are really awesome kevin
What if I want to set --shadow from an ancestor instead? Say, I have some theme classes, and the different themes have different shadow colors, and I want to set the theme for an entire section. If I have --shadow: red, then it's red, even if the theme has --shadow as something else. If I have --shadow: var(--theme-shadow, red);, now if an ansestor is declaring "--theme-shadow", it'll work... but I'm sort of handcuffing myself to --theme-shadow. You could open that up to something else, like or have like an "var(--shadow, var(--default-shadow)" or something, but it all gets a bit messy imo. By having a --_shadow: var(--shadow, fallback);, we have a default, but that default can be overwritten like I did here, OR by an ancestor outside of it, but if the inner one does have a specific color declared, that will win. I probably should have given this example in the video as well.
You can just create one set of styles and then just control colour details depending on its variant. Imagine a button primary, secondary, tertiary. And for example info-boxes. Confirmation, notification and error (red bg etc). You can do the same And then imagine that within those components you can easily override colours for specific button variants in error box. And so on. Not to mention easy recolouring for dark theme etc. It’s very powerful concept
I don't quite get the benefit of using the private version. If --shadow is the design token for shadows in the project, then why not just use that and redefine in local scopes like you have?
He mentioned it having to do with the cascade so I think it’s meant to guard against the initial default declaration accidentally having higher precedence than whenever you try to override it.
@@garretmhhmm but wouldn't the redeclaration in the modifier class overwrite the variable in root anyway? 🤔. I'm not sure now. Have to do some tests...
You can’t have a fallback without declaring another variable or altering the parent scope. . Additionally the private scope indicator makes it more explicit that you’re defining the variables for this whole component.
I do like your way of applying custom variables and that is what I often use myself. However there are cases where just having the directives is much better. One such case is the backoffice my clients use, that is because they like to customize absolutely everything and just applying a class with the color, or background, or hover effects and etc becomes less cumbersome and lighter than declaring all possible options.
Agreed. Classes are composable so I find it a lot more useful for things like variants. Though, grouping properties to a class is also useful for compound variants.
Yep. I added customizable themes to a site I worked on by generating a css class from user input that contains redefinitions of my vars and just applied it to the body.
Classes are powerful, but comparing classes to properties is comparing apples to oranges. They may both be CSS but they serve different purposes. For instance to animate a classes color to be reactive to the mouse, you just set the mouses x and y coordinates to a css property with JS. To do the same with classes would requires maintaining a virtual style sheet and redefining a class hundreds of times per frame (insanity).
If styles are mean to be reused accross your entire application, what sense has a locally scoped CSS variable. The key in using a style guide is that you set the styles and then use them, so that you create consistency in the UI. So basically you will use the same x colors and the same y typographies in all the componentes.
For overwriting, as you saw here. He still can have global styles, but he made small changes to each one by just changing a variable that only effected each local card. In this case his card component would have the typical card styles it inherits from the root or the base card component css, and then for specific instances he can choose to change a property of it without even needing to mention that property (i.e background-color, border-radius etc). I like that this approach doesn’t require you to target a specific property, just declare a local variable to a value that will automatically be applied to the relevant properties on component that is using them.
I think the solution is great, just use the CSS cascade because it's really powerful, but the local variable is completely useless. You could just do it without them and it will work out exactly the same way (except for the fallback value, but that could be declared in the root scope).
@@gileee It is less explicit by design. It is abstraction in order to reduce repetition and to reduce the amount of places where you need to adjust things if you want to change something. Sometimes you need to introduce a little bit of added complexity in order to prevent future problems.
@@CottidaeSEA Aaaand your last sentence is how you get that awful codebase in the company only one person works on and no one else wants to touch with a 10 foot pole. Adding abstractions in order to solve problems before they exists. Like kriffos above said. There's already a solution to this that doesn't require extra code being written prematurely.
First of all -- amazing video.. ...Please do include 00:00 timestamp in the timestamp pannel in your description or else they won't show up in the video ...and truly it was an awesome detail for me, it would be amazing to explore css this way.. time to include these in projects xD... thanks man! ❤️
I ended up doing a very similar thing in my windows 2000 desktop recreation (it is actually pixel and color perfect) where elements use css variables that I define by applying a class full of them describing a color scheme (w95/w2k). And sometimes that too refers to another variable like a common color, or calculates shadow/highlight colors based on the variable in the scheme. It's really cool!
Sitting here just hours after watching this video, having fixed a blocker that popped up some minutes ago with *exactly* isolate/z-index voodoo that I had just learned from you. Crazy! Thanks, also from my client :)
It's really nice to be able to control inheritance. Sometimes I use the pseudo-private fallbacks, and sometimes I just assign my default variables to the component directly. The first one makes my components really susceptible to inheritance, and the second one forces people to target my components directly if they want to override something.
Yet another brilliant video! Thank you sooo much for posting this! Tips like this can really reduce "bloat" of CSS files, keeping external stylesheets lean, mean and fast loading. :) Thank YOU!!!!!!!
I'm confused as to why you wouldn't use the same approach for box-shadow. Surely you could declare the following: .plan { box-shadow: ... -1rem -1rem 0 0 var(--shadow); } and then add each custom property to the modified selectors as with the others? Then you wouldn't have to redeclare each box-shadow rule every time.
It's called Block Element Modifier (or BEM). I use it for all my projects. If you Google it, first result will explain why it's a sensible naming pattern.
This is actually mind blowing. I saw this video before and it stuck with me and the only place I could find it again was this video. AI has generated a similar effect but was unable to figure out what I was referring to when I tried to describe it later.
This person deserve all the frontend development subscribe button!!!.. I've just recently found YT channel and i found it very helpful!! discovering new things and learning some tips and trick from you amazing! Thank you for sharing all your knowledge to us
Yeah, I feel the same. When you start getting "clever", you have to ask is it worth it? I don't feel the there's much to gain between the original and the custom property cleverness.
If there were were other thing that i can do more than subscription, i would do it without losing a minute. thank you so much for such an awesome video!!
Love this method I’m using this for components like statuses, pills, tags, info boxes or buttons. Default styles and using the same method I add themes for each variant.
This is an interesting approach, having _ as private properties is such a neat trick. Will try to incorporate into my future projects. Am already struggling with multiple css variables naming as I have so many. Like --js-varname are JS controlled variables and --d-varname are derived variables that often are a calc(), clamp() of a number of other variables so on and forth.
I definitely like the use of tokenizing in the variable name to make them more semantic. Brings a little bit of vim script into css. :) (For the uninitiated: variables in vim script files are prefixed with tokens like l: to denote a script-local variable to the interpreter, and g: to denote an application-global variable, and so on.)
I like those *--modifier selectors containing only the variables redeclaration, but I'm still not sure why do we need them "pseude-private" properties. Would it work the same without underscored versions?
I had to slow this video down to .75 playback speed to understand 😂 but after a few times of listening to the explanation and seeing it, my brain is already thinking of the possibilities 💚
This approach reminds me kinda of all the inheritance stuff we have in languages such as Java or C# (and many others). It feels natural on the one side, but makes me shiver in fear if I think about having to search for an override. Though maybe it's kinda more tidy. Thanks for the video!
I was thinking that too. On the surface, and for simple situations this can be very handy, but it could get very complicated very quickly if you are not careful. As long as you strictly follow a low coupling and high cohesion approach to things you should be good, but if you ever get into a high coupling or low cohesion situation this will get ugly and hard to maintain fast.
I’m all in on tailwind these days and it’s these reasons exactly. I hate having to search for css declarations that are in another place and can be obfuscated like this. I would much rather define how it looks in my html, it’s faster to do the first time, doesn’t involve all this setup, and is easier to understand when coming back to the code later
@@dave_jones I totally agree! CSS should be very easy to read and very clear. I don't understand people who don't want to write two lines of code more, just to show us that they can do it the other way. Any sort of abstraction like this one is completely unnecessary.
@@oblakus Agreed, what we're seeing here seems like a way to say "look how clever I can be" rather than actually being an efficient way to develop. I will grant that in some rare cases when you decide an entire design needs to change (such as "I don't want it pink anymore, I want it blue") then you have to change the class name across possibly many elements, but assuming we have a consistent style, if you decide that pink-500 should be a different color, you can modify the theme rather than change a css variable. Obviously there are always tradeoffs, but I really hate old-school css-selector styling.
@@dave_jonesbut in this way, pink-500 wouldn't be pink-500 anymore, will be other color, and you will make your code a lie for those who will read it later. And using your line of thinking, you can do the same with the custom properties and some theme classes, the difference is that you won't rely in a external abstraction anymore, you use the platform and won't have a unreadable HTML anymore.
I don't like the more specific selector setting a normal var and having that control a pseudo-private property on a more generic selector. I'd basically invert that pattern and set properties first to a pseudo-private property, then a public property, then a fallback. Each special version would set it's private custom property.
I feel like it's mostly linked to the philosophy of design tokens, inheritance and solid fallbacks. This fits really well with the BEM way of doing things too.
This is introducing spaghetti into your styles, thanks for the idea though. Also, you would have to explain with comments for others working with your code, I can see this turning into a mess quickly
Not sure the pseudo-locally scoped custom property really adds anything here if you're ultimately just using classes to set their values anyway. .text-red { --my-text-colour: red; } .text-green { --my-text-colour: green; } p { color: var(--my-text-colour); } Is this just what you're doing anyway? Why mess with the additional properties local to p?
If you're just using utility classes, then sure. The idea here is more on a component level, where I'm going to have defaults for my text-color, icon-color, shadow, etc. You don't have to do it like I showed here, I could have simple had: .plan { --shadow: pink; --icon: red; --button-hover: red; ... } And those would work as my default values, and then I could overwrite them where needed with modifiers, like I did. The advantage of definding the variable with a second variable and a fallback is that second variable can be set by other anscestors as well, which I didn't directly mention in the vide, but I should have. So, let's say I had a . If I took the above approach, the .plan defaults would always win. If I used what I showed in this video, if .dark-theme declares something for --shadow, or --icon, etc, then those values will work because custom properties are inherited (maybe dark theme isn't the best example here, but I think the point stands). I hope that makes sense :)
@@KevinPowell I see what you're getting at but it still very much feels like overcomplicating a use case to prove the validity of the approach. Why would you set different values on .plan when .dark-theme and .light-theme would be the central resource for everything and all their descendants to just inherit? I do enjoy bending CSS to my will just to see how far you can push it (playing with trigonometry using just CSS variables and math functions to animate a light sweep effect at any angle was mind bending), but so much these days feels like we're too excited by the amount of tools available we never take a step back and just process which subset of them ae appropriate.
IMO, you only get the illusion that everything is well and nicely modularized. If you think about it, your html is poluted with many very specific classes and ids just so that you can make these cool declarations. Just inline the --shadow directly in the html would actually make more sense here
Is there a reason why you use `--_shadow: var(--shadow, pink)`instead of `--shadow: pink`? Wouldn't this make it default to pink, and then it can be overwritten in other classes? Is there maybe some specificity problems I'm not thinking of?
I think I did read that with Custom Property fallbacks it will take a little longer to calculate because both values have to be read, is that so and is it significant enough to avoid using fallbacks inside custom props?
My general rule is, if you're worried about optimizing your CSS, you're really getting into the weeds. There are exceptions, and crazy selectors that can take time to evaluate, but in general, you'll probably have *much* bigger gains with easy optimizations of images and other assets, followed by JS. You'll be looking at microsecond improvements most of the time with CSS (again, most of the time, there are times where it can be an issue, but it will probably be selector related, and not custom property usage, unless you have like 10,000 of them declared in your root and you're overiding them throughout your project)
Presumably these “pseudo private” variables are used only within “nested” BEM elements? If so, I would call them “protected” variables since they are behaviourally similar to protected variables in Object Oriented class inheritance :)
The property technique seems great for something like isolated CSS files in Blazor, as the fallback could be defined in the component.css for re-usability sake but you could override it in the site.css root if needed.
Can you use a custom property within another one? So for example var(--clr-var(--targetColor)-300) to simplify this down to one line of css per selector? Set the .plan to be that, and then set the --targetColoe property on a pram/bike/rocket? level
No, we can't do that. What we could do though, is break apart an hsl value to make it easier. So, you'd have something like fill: hsl(var(--hue, 200) 50% 50%); and the same thing for your shadow, but with a different lightness value, and then if you change the --hue, it'll change change anything using it. And you could do the same with the saturation and lightness as well.
I'm not a fan of the prefixing _ for "private" properties. It doesn't tell you where the property is defined, so all you know is "this wasn't defined in the :root". That said, the basic idea of using your cascade and variables wisely is excellent. I agree (especially in a BEM environment) that you should be able to set up some helpful vars and use them in descendants for control and maintenance.
I also often use CSS vars for shared things like height/width or left/right or top/bottom values. I do something like `--size: 100px;` often so I only have to change it in one prop. Super useful in dev tools.
if i have --_shadow-color: 220 3% 15%; --_shadow-strength: 1%; --shadow-1:--shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color) / calc(var(--_shadow-strength) + 9%)); can i reassign it? on another scss file? like this? --_shadow-color: 001 1% 1%; --_shadow-strength: 001 1% 1%; box-shadow: var(--shadow-5);
Hi. I love watching you videos and I have learned a lot, also have improved my css skills. One question however I would like to know in css/ html. How do you create a learning webpage. With two columns. One column has links that open in other column. Not using or tables. Exampl w3schools, or javatpoint. Etc
I'm personally not a fan. I like inheritance, however I think its less readable. You'd read --shadow: 'color', but shadow of what? You'd have to scroll in your css file or basically debug inside dev tools to know where and how it is used.
The custom property clutter is the main reason why I use sass to generate properties during compilation. Keepin the dev code manageable. But this guide should change it. 😎
Quick question regarding the double box shadow approach: I thought you were able to use variables for box shadow colors, too, so could you not just use a placeholder like your privately scoped variable?
totally, but you'd still have to declare the box shadow every time if not using a custom, internal property (instead of declaring the box shadow once and declaring only the custom properties in the specific class)
I'm by no means a professional CSS writer, I do systems for work and I write UIs for hobbies, but I have a question regarding the classes plan and plan--pram etc. I notice that you have these as seemingly individual, unrelated classes. When I write CSS, I use attribute selectors to write inheritance, for example: [style|="plan"] { #CSS } Then I'd do .plan-pram { #css } Is this bad practice? Are there performance concerns, or is it just not clean, or is it fine and it's just not done here for demonstration purposes? I personally like this way as it feels more descriptive without repeating yourself, so you get all the properties from the plan class, while only saying style="plan-pram", which to me obviously represents a plan.
One topic I don't see anyone covering is the CSS part() pseudo selector. I'm trying to figure out if it is possible to combine utility classes into a new class as was intended with the @apply directive, but it was abandoned for various reasons I don't quite understand. Instead, we got a "replacement" called parts, which I still don't understand. How can this be used to accomplish the same thing? If not in native CSS, then is it possible in SASS (without using @extend, which basically appends the extended class to other classes - a messy solution)?
The box shadow on the back of the cards. Thank you so much for responding kevin and for all the efforts of making a high quality videos ❤ love from the philippines
Interesting approach Kevin. The one problem I find with this type of “complex but elegant code” whether CSS or Javascript, is when I come back to it a year later and try and understand why I did it this way it takes me longer to figure it out. Especially if I’ve really got my head into something and am “ten layers deep” in the problem…Sometimes I find a less elegant way can be more obvious later on.
I totally agree there is a balance to find, but with this, I find it makes things so much more robust and usable. Of course, you can simplify this a little and still use locally scoped properties without the extra layer too 😊
@@KevinPowell Could you expand a bit on how you find it becomes more robust? As a counterclaim I would say that you need to spam comments a lot to make it easy for for the next guy.
. @KevinPowell Yes, also this being CSS it would not be unusual to integrate this into every job. Often in Javascript a chunk of code can be a “one off” for a particular (often arcane) problem that is particular to that application and never used again
Approach is nice with reusing things! LoL, CSS reinventing functions and variable scoping, new programming language))) but with -- variables, fyy better to use preprocessor
fine except the way you first said you dont like has an extremely useful reason ... themes. You can have any amount of classes to represent your theme colors with only variables , normally its just light and dark themes. Anyway switch out that class on the body tag and all css using the variables update. You might have some other css guru method of doing that , but as a programmer myself , I can just say , its easy , its works , it ticks the boxes on so many levels for scalability or making changes .. and works in all frameworks and browsers. Let me also ask .. why the heck do you even need a fall back color in css? its a color , not an external asset. When will this ever be the case ? You even base you code on using the fallback as the first option , because youactually structure your code to not use the first option? You defaulting to the fallback?
Great video, thx :) But I do wonder why the extra variable is used. The following would give the same result, with one variable less. .plan { --shadow: red background: var(--shadow); } .other-plan { --shadow: blue; }
because someone may wonder why there are two different properties for the same variable. But when you explicitly use "private" variables that doesn't confuse too much
Kevin, why don't you use instead of pure colors like red or blue, colors like crimson or royalblue? It's less aggressive and looks more pleasing to the eyes.
Depends on the demo, but here I went with red to make it obvious. If it were bigger things, that were bright on the screen, or if I'd been leaving them, I fully agree... Red is short and fast though, and sometimes I'm lazy 😅
Great stuff as usual 👍 How about a video on styling issues we might face on different operating systems…? I’m building a web app that only needs to run in Chrome based browsers (it’s an internal system) and I’m developing on MacOS. If I view the page in windows I get layout issues. For example a simple header row with display grid and 2 columns, looks fine for me but in windows the second column in the second column shows up in the correct horizontal position but looks like it’s on a row below in windows…
tbh, I've never heard of major inconsistencies between operating systems, with the same browser. The only difference I can think of is that the two systems render fonts a little differently, so a `font-weight: 300` might seem a little lighter in one than the other, which can actually cause line-breaks in different places.
@@KevinPowell I tried setting the font-family to Arial and it sorted the fonts out but not the layout. I’ll come back to this another day and let you know what the problem turns out to be… assuming I figure it out that is. The most annoying difference is the emojis. I switched from SVG to emoji for folder and document icons etc. The ones in macOS are stunning, the ones on Windows 10 look like something from the days of Windows XP. Such a shame as the Mac ones are high def 3d and being part of the operating system don’t have to be downloaded. I’m tempted to show emoji on Mac and Svg on windoze… I’ve been using windows at work since version 3.1, every release since XP has been a disappointment lol… anyway, thanks again for the vids they’re a great help…
While you won't get pixel perfect layouts due to font rendering, there's at least one main thing which is scrollbar gutters being reserved on Windows and overlay on Mac (Linux does whatever they want, of course), which is why Apple blocking "overflow: overlay" pissed me off so much, since it's certainly what you intended and it's the standard even on Windows now. The best you can do without custom JS scrollbars (generally a really bad idea) is to use scrollbar-gutter and scrollbars-width to at least ensure they're consistent across OS... except Safari still hasn't implemented scrollbar-gutter, making it pointless for general use. Infuriating.
@@SimonBuchanNz that was part of the problem. The original code was also over complex (nested components in Svelte). I scrapped it and started again removing some unnecessary nesting and it’s sorted 👍 I’m pretty sure there was something else wrong but figured it was quicker to start over
For somerhung like this, using @mixins in sass is better becuase in sass you can declare variables and functions properly and not have to make something that emulates private and public varubles
IMHO It would be more readable to: 1) keep defining a local/private property of shadow: _shadow exactly as you do, but 2) to redefine this private property "_shadow" in the variants, not the global property "shadow" which has been used as a default value. Because it could be not used anymore in the future if the designer decides to use another default value. In this case, the designer would have to **know** that it was used in the variants. You say later in the video that when you use a value, it's better to use the private version, I would also apply this principle to the selector which redefines locally the local values to the *private* properties instead of global ones.
I really like the concept of making it possible to make your styles extensible. But there is something that I find annoying I saw you and a lot of others doing: naming variables like --clr-yellow-400, or --clr-blue-300. Just imagine you have to change evething that uses "--clr-yellow-400" to red, for exemple. You will have 2 options: change the variable content or replacing every usage with another variable named --red-something. Either way you will get a messed code by unrelated name-content or because if you have to replace everything manually anyway, you should have not used a variable in the first place
I have a very simple shell script that let's me do this for a ton of files. Enter directory to change Enter a regex to match the files to change Enter the offending regex: --clr-yellow-400 Enter the new version: --clr-blue-300 Files changed. Very fast, very easy. Just change manually the color value and name where it is actually defined first. One file or two, in your editor. 30 files, use the script. Changing "doog" to "dog" in a whole website in seconds is sooo nice.
@@CrispyCircuits I know there are such features in most ides and some bash scripts. In fact the most "simple" ides, like Notepad++ provides code replacement features by plain text or regexes. External tools aside, this is still a misunderstanding of variables usage...
This is neat, but it seems trying build a table with just one paint roller. It can paint the surface better, but do poorly cutting woods, drilling holes, or hitting nails. I use css variables with local overriding. There are more than handful ways to achieve this, and doing everything in CSS doesn't feel right to me.
Wouldn't this work exactly the same without the underscores? The idea of private variables in general programming is not to denote locality, but as a "don't use me outside this module". That's how it's used in python, for example, where the _ is just a convention, saying that these could change at any time and won't be marked as a breaking change once a package updates. Using the same name for an internal variable is called "shadowing" (en.wikipedia.org/wiki/Variable_shadowing) and it's a completely valid approach to the matter.
@@rossclutterbuck1060 does python have as private keyword now? good to know!! back on python 2 and early days python 3, it was just convention. good stuff!!
Very good demo on how to utilise this.
I’ve been doing this for a while and a big win is coming back over time and making changes. So much easier to understand.
I end up with three groups per component. (
- Private custom props with corosponding registered properties
- Rules with the private props
- modifier that set the registered properties.
It's ok to define a color pallete with variables, but I definitely recommend defining a semantic palette on top of that for components to use. The semantic palette can be assigned at runtime for different color schemes (high contrast, dark mode, etc), and components don't need to know anything about the actual colors.
Can you provide an example of "semantic" palette?
@@collimarco not the original commenter but this is how I do it: I have two level of variables: synonyms and semantics;
synonyms are things like "--cl-red: #f71010" (as per the client's brand manual), while semantics are like "--cl-danger: var(--cl-red)".
In some places, I'd use "--cl-red" because the element is simply red, in others I'd use "--cl-danger" because the element performs a dangerous operation. This way, I can later redefine it as "--cl-danger: var(--cl-orange)" on darker themes, and all the dangerous elements would turn orange, while the elements that are red for aesthetic reasons wouldn't change.
This could be applied for the whole theme, with the semantics changing while the synonyms stay the same, because they were lifted straight from the client's visual guidelines.
He means using variable names like “primary color” over “blue 400”
Exactly. Use color variables that are meaningful to their purpose, not the actual hex/rgb value. Then those meaningful color variables can be assigned different values based on any criteria we want without requiring all the components in the design system to change.
Establishing that set of meaningful variables requires a bit of thought - usually a lot of discussion with designer. One would hope the design system doesn't end up with 30 different variables for different backgrounds. Typically designers would refer to those in their specs.
I have learned this technique from your css demstified course and I really like it and I love the fact that you are making it on TH-cam also and to see how you also evolved in thinking from that point
You are really awesome kevin
What's the benefit of the private variable over just declaring --shadow: red; and then overwriting it in the other classes?
Yep. Same here .. ??
What if I want to set --shadow from an ancestor instead? Say, I have some theme classes, and the different themes have different shadow colors, and I want to set the theme for an entire section. If I have --shadow: red, then it's red, even if the theme has --shadow as something else. If I have --shadow: var(--theme-shadow, red);, now if an ansestor is declaring "--theme-shadow", it'll work... but I'm sort of handcuffing myself to --theme-shadow. You could open that up to something else, like or have like an "var(--shadow, var(--default-shadow)" or something, but it all gets a bit messy imo.
By having a --_shadow: var(--shadow, fallback);, we have a default, but that default can be overwritten like I did here, OR by an ancestor outside of it, but if the inner one does have a specific color declared, that will win. I probably should have given this example in the video as well.
You can just create one set of styles and then just control colour details depending on its variant. Imagine a button primary, secondary, tertiary. And for example info-boxes. Confirmation, notification and error (red bg etc). You can do the same
And then imagine that within those components you can easily override colours for specific button variants in error box.
And so on.
Not to mention easy recolouring for dark theme etc.
It’s very powerful concept
I don't quite get the benefit of using the private version. If --shadow is the design token for shadows in the project, then why not just use that and redefine in local scopes like you have?
Maybe to keep the re-definition localised? Am not sure either
He mentioned it having to do with the cascade so I think it’s meant to guard against the initial default declaration accidentally having higher precedence than whenever you try to override it.
@@garretmhhmm but wouldn't the redeclaration in the modifier class overwrite the variable in root anyway? 🤔. I'm not sure now. Have to do some tests...
Some benefits I see: the private properties are a kind of documentation, and they are grouped without being mixed up with unrelated stuff.
You can’t have a fallback without declaring another variable or altering the parent scope. . Additionally the private scope indicator makes it more explicit that you’re defining the variables for this whole component.
I do like your way of applying custom variables and that is what I often use myself. However there are cases where just having the directives is much better. One such case is the backoffice my clients use, that is because they like to customize absolutely everything and just applying a class with the color, or background, or hover effects and etc becomes less cumbersome and lighter than declaring all possible options.
Agreed. Classes are composable so I find it a lot more useful for things like variants. Though, grouping properties to a class is also useful for compound variants.
Yep. I added customizable themes to a site I worked on by generating a css class from user input that contains redefinitions of my vars and just applied it to the body.
Classes are powerful, but comparing classes to properties is comparing apples to oranges. They may both be CSS but they serve different purposes. For instance to animate a classes color to be reactive to the mouse, you just set the mouses x and y coordinates to a css property with JS. To do the same with classes would requires maintaining a virtual style sheet and redefining a class hundreds of times per frame (insanity).
If styles are mean to be reused accross your entire application, what sense has a locally scoped CSS variable. The key in using a style guide is that you set the styles and then use them, so that you create consistency in the UI. So basically you will use the same x colors and the same y typographies in all the componentes.
For overwriting, as you saw here. He still can have global styles, but he made small changes to each one by just changing a variable that only effected each local card.
In this case his card component would have the typical card styles it inherits from the root or the base card component css, and then for specific instances he can choose to change a property of it without even needing to mention that property (i.e background-color, border-radius etc).
I like that this approach doesn’t require you to target a specific property, just declare a local variable to a value that will automatically be applied to the relevant properties on component that is using them.
@@TheStickofWar That sounds less explicit, and in the already confusing world of cascading effects that sounds worse tbh.
I think the solution is great, just use the CSS cascade because it's really powerful, but the local variable is completely useless. You could just do it without them and it will work out exactly the same way (except for the fallback value, but that could be declared in the root scope).
@@gileee It is less explicit by design. It is abstraction in order to reduce repetition and to reduce the amount of places where you need to adjust things if you want to change something.
Sometimes you need to introduce a little bit of added complexity in order to prevent future problems.
@@CottidaeSEA Aaaand your last sentence is how you get that awful codebase in the company only one person works on and no one else wants to touch with a 10 foot pole. Adding abstractions in order to solve problems before they exists. Like kriffos above said. There's already a solution to this that doesn't require extra code being written prematurely.
First of all -- amazing video..
...Please do include 00:00 timestamp in the timestamp pannel in your description or else they won't show up in the video
...and truly it was an awesome detail for me, it would be amazing to explore css this way.. time to include these in projects xD... thanks man! ❤️
Ooops, I always have that 00:00 one in there, no idea what happened there but thanks for letting me know! Also glad you enjoyed it :)
@@KevinPowell Most Welcome Sir
I use this approach in conjunction with angular component’s bindings. Works like magic.
You mean to add custom styles to your component and if no custom styles set then your component will revert to default styles instead, right ?
@@deadlyecho yes
@HostBinding(“styles.-icon-color”)
iconColor = “black”;
I ended up doing a very similar thing in my windows 2000 desktop recreation (it is actually pixel and color perfect) where elements use css variables that I define by applying a class full of them describing a color scheme (w95/w2k). And sometimes that too refers to another variable like a common color, or calculates shadow/highlight colors based on the variable in the scheme. It's really cool!
Nice - do you have a link? I would be curious to see your project
There is always something new in your videos, really helpful 💕💕
Sitting here just hours after watching this video, having fixed a blocker that popped up some minutes ago with *exactly* isolate/z-index voodoo that I had just learned from you. Crazy! Thanks, also from my client :)
It's really nice to be able to control inheritance. Sometimes I use the pseudo-private fallbacks, and sometimes I just assign my default variables to the component directly.
The first one makes my components really susceptible to inheritance, and the second one forces people to target my components directly if they want to override something.
Yet another brilliant video! Thank you sooo much for posting this! Tips like this can really reduce "bloat" of CSS files, keeping external stylesheets lean, mean and fast loading. :) Thank YOU!!!!!!!
I'm confused as to why you wouldn't use the same approach for box-shadow. Surely you could declare the following:
.plan {
box-shadow:
...
-1rem -1rem 0 0 var(--shadow);
}
and then add each custom property to the modified selectors as with the others? Then you wouldn't have to redeclare each box-shadow rule every time.
He does that at 13:28
Very nice technique. I will definitely adopt this one. By the way, what is the "--" and "__" convention?
It's called Block Element Modifier (or BEM). I use it for all my projects. If you Google it, first result will explain why it's a sensible naming pattern.
@@THEunderscoreJOKE thanks
My goodness, CSS sure has improved a lot in the past 10 years or so since I last really dabbled in it!
This just reminds me why I’m glad I made the switch to tailwind.
This is actually mind blowing. I saw this video before and it stuck with me and the only place I could find it again was this video. AI has generated a similar effect but was unable to figure out what I was referring to when I tried to describe it later.
This person deserve all the frontend development subscribe button!!!.. I've just recently found YT channel and i found it very helpful!! discovering new things and learning some tips and trick from you amazing! Thank you for sharing all your knowledge to us
I always love your videos and pretty much always agree with your opinions. But in this instance I think this method is more confusing.
It's definitely a bit more work to setup, but with the payoff of being a lot simpler to use later on.
Yeah, I feel the same. When you start getting "clever", you have to ask is it worth it? I don't feel the there's much to gain between the original and the custom property cleverness.
If there were were other thing that i can do more than subscription, i would do it without losing a minute. thank you so much for such an awesome video!!
Love this method
I’m using this for components like statuses, pills, tags, info boxes or buttons.
Default styles and using the same method I add themes for each variant.
This is an interesting approach, having _ as private properties is such a neat trick. Will try to incorporate into my future projects. Am already struggling with multiple css variables naming as I have so many. Like --js-varname are JS controlled variables and --d-varname are derived variables that often are a calc(), clamp() of a number of other variables so on and forth.
I definitely like the use of tokenizing in the variable name to make them more semantic. Brings a little bit of vim script into css. :) (For the uninitiated: variables in vim script files are prefixed with tokens like l: to denote a script-local variable to the interpreter, and g: to denote an application-global variable, and so on.)
I like those *--modifier selectors containing only the variables redeclaration, but I'm still not sure why do we need them "pseude-private" properties. Would it work the same without underscored versions?
I had a similar question on this.
Custom properties are such a saviour to DRY code
I had to slow this video down to .75 playback speed to understand 😂 but after a few times of listening to the explanation and seeing it, my brain is already thinking of the possibilities 💚
This approach reminds me kinda of all the inheritance stuff we have in languages such as Java or C# (and many others). It feels natural on the one side, but makes me shiver in fear if I think about having to search for an override. Though maybe it's kinda more tidy.
Thanks for the video!
I was thinking that too. On the surface, and for simple situations this can be very handy, but it could get very complicated very quickly if you are not careful. As long as you strictly follow a low coupling and high cohesion approach to things you should be good, but if you ever get into a high coupling or low cohesion situation this will get ugly and hard to maintain fast.
I’m all in on tailwind these days and it’s these reasons exactly. I hate having to search for css declarations that are in another place and can be obfuscated like this. I would much rather define how it looks in my html, it’s faster to do the first time, doesn’t involve all this setup, and is easier to understand when coming back to the code later
@@dave_jones I totally agree! CSS should be very easy to read and very clear. I don't understand people who don't want to write two lines of code more, just to show us that they can do it the other way. Any sort of abstraction like this one is completely unnecessary.
@@oblakus Agreed, what we're seeing here seems like a way to say "look how clever I can be" rather than actually being an efficient way to develop. I will grant that in some rare cases when you decide an entire design needs to change (such as "I don't want it pink anymore, I want it blue") then you have to change the class name across possibly many elements, but assuming we have a consistent style, if you decide that pink-500 should be a different color, you can modify the theme rather than change a css variable. Obviously there are always tradeoffs, but I really hate old-school css-selector styling.
@@dave_jonesbut in this way, pink-500 wouldn't be pink-500 anymore, will be other color, and you will make your code a lie for those who will read it later.
And using your line of thinking, you can do the same with the custom properties and some theme classes, the difference is that you won't rely in a external abstraction anymore, you use the platform and won't have a unreadable HTML anymore.
Thank you for blessing us with this
That's pretty smart Kev! I like that pretty much!
Thanks for the tips ! i find your videos full of useful information!
I don't like the more specific selector setting a normal var and having that control a pseudo-private property on a more generic selector. I'd basically invert that pattern and set properties first to a pseudo-private property, then a public property, then a fallback. Each special version would set it's private custom property.
I feel like it's mostly linked to the philosophy of design tokens, inheritance and solid fallbacks. This fits really well with the BEM way of doing things too.
Yes, theming with CSS using as few declarations as possible is an art, and CSS is getting better and better these days.
This is introducing spaghetti into your styles, thanks for the idea though.
Also, you would have to explain with comments for others working with your code, I can see this turning into a mess quickly
This idea is so similar to declaring and re-declaring JavaScript let variable and the concept of block scope.
Not sure the pseudo-locally scoped custom property really adds anything here if you're ultimately just using classes to set their values anyway.
.text-red {
--my-text-colour: red;
}
.text-green {
--my-text-colour: green;
}
p {
color: var(--my-text-colour);
}
Is this just what you're doing anyway? Why mess with the additional properties local to p?
If you're just using utility classes, then sure. The idea here is more on a component level, where I'm going to have defaults for my text-color, icon-color, shadow, etc.
You don't have to do it like I showed here, I could have simple had:
.plan {
--shadow: pink;
--icon: red;
--button-hover: red;
...
}
And those would work as my default values, and then I could overwrite them where needed with modifiers, like I did.
The advantage of definding the variable with a second variable and a fallback is that second variable can be set by other anscestors as well, which I didn't directly mention in the vide, but I should have.
So, let's say I had a . If I took the above approach, the .plan defaults would always win. If I used what I showed in this video, if .dark-theme declares something for --shadow, or --icon, etc, then those values will work because custom properties are inherited (maybe dark theme isn't the best example here, but I think the point stands).
I hope that makes sense :)
@@KevinPowell I see what you're getting at but it still very much feels like overcomplicating a use case to prove the validity of the approach. Why would you set different values on .plan when .dark-theme and .light-theme would be the central resource for everything and all their descendants to just inherit?
I do enjoy bending CSS to my will just to see how far you can push it (playing with trigonometry using just CSS variables and math functions to animate a light sweep effect at any angle was mind bending), but so much these days feels like we're too excited by the amount of tools available we never take a step back and just process which subset of them ae appropriate.
I prefer to prefix pseudo-private properties with a block name instead of an underscore, so it would be --plan-shadow: var(--shadow), and so on
Why didn't you use nested css instead of repeated selectors ?
An insanely elegant solution! in a class like `.plan.plan--pram`, the `.plan--pram` acts as the custom property provider whereas `.plan` is a consumer
This is a gem, thanks for the video
Wow, that is a really nice way of using custom properties!
actually nice approach ❤
IMO, you only get the illusion that everything is well and nicely modularized. If you think about it, your html is poluted with many very specific classes and ids just so that you can make these cool declarations. Just inline the --shadow directly in the html would actually make more sense here
would this look the same in sass, or is there a simpler way of achieving it through sass?
Is there a reason why you use `--_shadow: var(--shadow, pink)`instead of `--shadow: pink`? Wouldn't this make it default to pink, and then it can be overwritten in other classes? Is there maybe some specificity problems I'm not thinking of?
--_shadow: var(--shadow, pink) pink color is in this case used as a fall back color if --shadow is not declared yet
Hi, why not setting the _shadow and _icon directly in the classes. Why do we need 2 variables?
I use double variables like this:
.icon{
/*dimensions*/
--large:30px
--medium:20px;
--small:10px;
--size:var(--medium);
width:var(--size);
height:var(--size); /* or aspect-ratio:1; */
/*select an icon from its sprite image (10 by 10 equally-sized slots)*/
--row:1;
--column:1;
background-size:calc(var(--icon-size) * 10);
background-position-x:calc(calc(var(--icon-size) * -1) * calc(var(--column) - 1));
background-position-y:calc(calc(var(--icon-size) * -1) * calc(var(--row) - 1));
}
.particular-icon{
--size:30px;
--row:1;
--column:5;
}
I think I did read that with Custom Property fallbacks it will take a little longer to calculate because both values have to be read, is that so and is it significant enough to avoid using fallbacks inside custom props?
My general rule is, if you're worried about optimizing your CSS, you're really getting into the weeds. There are exceptions, and crazy selectors that can take time to evaluate, but in general, you'll probably have *much* bigger gains with easy optimizations of images and other assets, followed by JS. You'll be looking at microsecond improvements most of the time with CSS (again, most of the time, there are times where it can be an issue, but it will probably be selector related, and not custom property usage, unless you have like 10,000 of them declared in your root and you're overiding them throughout your project)
Thank you for this AMAZING video! ❤
Nice tutorial, will use those techiqes, thank you
So we created prototype that we inherit properties from and change them to our needs right?
Basically, yes 😊
@@KevinPowell Awesome
Presumably these “pseudo private” variables are used only within “nested” BEM elements? If so, I would call them “protected” variables since they are behaviourally similar to protected variables in Object Oriented class inheritance :)
Is that how Tailwind CSS work?
We just slap it on Vanilla CSS3?
The property technique seems great for something like isolated CSS files in Blazor, as the fallback could be defined in the component.css for re-usability sake but you could override it in the site.css root if needed.
C is for cascade! Nice idea.
Can you use a custom property within another one? So for example var(--clr-var(--targetColor)-300) to simplify this down to one line of css per selector? Set the .plan to be that, and then set the --targetColoe property on a pram/bike/rocket? level
No, we can't do that. What we could do though, is break apart an hsl value to make it easier. So, you'd have something like
fill: hsl(var(--hue, 200) 50% 50%); and the same thing for your shadow, but with a different lightness value, and then if you change the --hue, it'll change change anything using it. And you could do the same with the saturation and lightness as well.
I love your videos abous css, and your aura.
Would the next level plan be Ludicrous Speed?
This is really great. As a programmer, this makes more sense
I'm not a fan of the prefixing _ for "private" properties. It doesn't tell you where the property is defined, so all you know is "this wasn't defined in the :root". That said, the basic idea of using your cascade and variables wisely is excellent. I agree (especially in a BEM environment) that you should be able to set up some helpful vars and use them in descendants for control and maintenance.
I also often use CSS vars for shared things like height/width or left/right or top/bottom values. I do something like `--size: 100px;` often so I only have to change it in one prop. Super useful in dev tools.
Also, your example of animations using variables is a great use-case for minimizing duplicated styles. Bravo 👏
if i have
--_shadow-color: 220 3% 15%;
--_shadow-strength: 1%;
--shadow-1:--shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color) / calc(var(--_shadow-strength) + 9%));
can i reassign it? on another scss file?
like this?
--_shadow-color: 001 1% 1%;
--_shadow-strength: 001 1% 1%;
box-shadow: var(--shadow-5);
Hi.
I love watching you videos and I have learned a lot, also have improved my css skills.
One question however I would like to know in css/ html.
How do you create a learning webpage. With two columns.
One column has links that open in other column. Not using or tables. Exampl w3schools, or javatpoint. Etc
I'm personally not a fan. I like inheritance, however I think its less readable. You'd read --shadow: 'color', but shadow of what? You'd have to scroll in your css file or basically debug inside dev tools to know where and how it is used.
thank you, this is a great job !!
The custom property clutter is the main reason why I use sass to generate properties during compilation. Keepin the dev code manageable.
But this guide should change it. 😎
Quick question regarding the double box shadow approach: I thought you were able to use variables for box shadow colors, too, so could you not just use a placeholder like your privately scoped variable?
Yeah, definitely!
totally, but you'd still have to declare the box shadow every time if not using a custom, internal property (instead of declaring the box shadow once and declaring only the custom properties in the specific class)
Why not declare the box shadow with a custom variable property as the background color ?
Also yes, I do wish to get the most "of of" my mobile ;)
I'm by no means a professional CSS writer, I do systems for work and I write UIs for hobbies, but I have a question regarding the classes plan and plan--pram etc.
I notice that you have these as seemingly individual, unrelated classes. When I write CSS, I use attribute selectors to write inheritance, for example:
[style|="plan"] {
#CSS
}
Then I'd do
.plan-pram {
#css
}
Is this bad practice? Are there performance concerns, or is it just not clean, or is it fine and it's just not done here for demonstration purposes?
I personally like this way as it feels more descriptive without repeating yourself, so you get all the properties from the plan class, while only saying style="plan-pram", which to me obviously represents a plan.
This was an awesome video Kevin! It's a lot of fun seeing all you can do with CSS
This is sort of like props passed to components in various frameworks.
One topic I don't see anyone covering is the CSS part() pseudo selector. I'm trying to figure out if it is possible to combine utility classes into a new class as was intended with the @apply directive, but it was abandoned for various reasons I don't quite understand. Instead, we got a "replacement" called parts, which I still don't understand. How can this be used to accomplish the same thing? If not in native CSS, then is it possible in SASS (without using @extend, which basically appends the extended class to other classes - a messy solution)?
Hi kevin do you have a video on how did you do that 3d box? Thank you
Which 3d box?
The box shadow on the back of the cards. Thank you so much for responding kevin and for all the efforts of making a high quality videos ❤ love from the philippines
Interesting approach Kevin. The one problem I find with this type of “complex but elegant code” whether CSS or Javascript, is when I come back to it a year later and try and understand why I did it this way it takes me longer to figure it out. Especially if I’ve really got my head into something and am “ten layers deep” in the problem…Sometimes I find a less elegant way can be more obvious later on.
I totally agree there is a balance to find, but with this, I find it makes things so much more robust and usable. Of course, you can simplify this a little and still use locally scoped properties without the extra layer too 😊
@@KevinPowell Could you expand a bit on how you find it becomes more robust? As a counterclaim I would say that you need to spam comments a lot to make it easy for for the next guy.
. @KevinPowell Yes, also this being CSS it would not be unusual to integrate this into every job. Often in Javascript a chunk of code can be a “one off” for a particular (often arcane) problem that is particular to that application and never used again
Approach is nice with reusing things! LoL, CSS reinventing functions and variable scoping, new programming language))) but with -- variables, fyy better to use preprocessor
Man, I love this.
Awesome, thank you!
fine except the way you first said you dont like has an extremely useful reason ... themes. You can have any amount of classes to represent your theme colors with only variables , normally its just light and dark themes. Anyway switch out that class on the body tag and all css using the variables update. You might have some other css guru method of doing that , but as a programmer myself , I can just say , its easy , its works , it ticks the boxes on so many levels for scalability or making changes .. and works in all frameworks and browsers.
Let me also ask .. why the heck do you even need a fall back color in css? its a color , not an external asset. When will this ever be the case ? You even base you code on using the fallback as the first option , because youactually structure your code to not use the first option? You defaulting to the fallback?
Great video, thx :)
But I do wonder why the extra variable is used. The following would give the same result, with one variable less.
.plan {
--shadow: red
background: var(--shadow);
}
.other-plan {
--shadow: blue;
}
because someone may wonder why there are two different properties for the same variable. But when you explicitly use "private" variables that doesn't confuse too much
This is a really usefull idea!
Kevin, why don't you use instead of pure colors like red or blue, colors like crimson or royalblue? It's less aggressive and looks more pleasing to the eyes.
Depends on the demo, but here I went with red to make it obvious. If it were bigger things, that were bright on the screen, or if I'd been leaving them, I fully agree... Red is short and fast though, and sometimes I'm lazy 😅
Great stuff as usual 👍 How about a video on styling issues we might face on different operating systems…? I’m building a web app that only needs to run in Chrome based browsers (it’s an internal system) and I’m developing on MacOS. If I view the page in windows I get layout issues. For example a simple header row with display grid and 2 columns, looks fine for me but in windows the second column in the second column shows up in the correct horizontal position but looks like it’s on a row below in windows…
tbh, I've never heard of major inconsistencies between operating systems, with the same browser. The only difference I can think of is that the two systems render fonts a little differently, so a `font-weight: 300` might seem a little lighter in one than the other, which can actually cause line-breaks in different places.
@@KevinPowell I tried setting the font-family to Arial and it sorted the fonts out but not the layout. I’ll come back to this another day and let you know what the problem turns out to be… assuming I figure it out that is. The most annoying difference is the emojis. I switched from SVG to emoji for folder and document icons etc. The ones in macOS are stunning, the ones on Windows 10 look like something from the days of Windows XP. Such a shame as the Mac ones are high def 3d and being part of the operating system don’t have to be downloaded. I’m tempted to show emoji on Mac and Svg on windoze…
I’ve been using windows at work since version 3.1, every release since XP has been a disappointment lol… anyway, thanks again for the vids they’re a great help…
While you won't get pixel perfect layouts due to font rendering, there's at least one main thing which is scrollbar gutters being reserved on Windows and overlay on Mac (Linux does whatever they want, of course), which is why Apple blocking "overflow: overlay" pissed me off so much, since it's certainly what you intended and it's the standard even on Windows now.
The best you can do without custom JS scrollbars (generally a really bad idea) is to use scrollbar-gutter and scrollbars-width to at least ensure they're consistent across OS... except Safari still hasn't implemented scrollbar-gutter, making it pointless for general use. Infuriating.
@@SimonBuchanNz that was part of the problem. The original code was also over complex (nested components in Svelte). I scrapped it and started again removing some unnecessary nesting and it’s sorted 👍 I’m pretty sure there was something else wrong but figured it was quicker to start over
For somerhung like this, using @mixins in sass is better becuase in sass you can declare variables and functions properly and not have to make something that emulates private and public varubles
Also have a cold, get well soon, buddy!
I was today years old when I found out var() could include a fall back value.
I was like where is he going with this for 50% of the video then the button hover moment i went woah that's clever!
non-:root custom properties are useful when you want to affect multiple elements with javascript like:
simple splitter
body,body:before,body:after{
margin:0;
position:fixed;
inset:0;
display:block;
}
body:before{
right:calc(100% - var(--d,50%));
content:"left side";
background-color:#F00;
}
body:after{
left:var(--d,50%);
content:"right side";
background-color:#0F0;
}
IMHO It would be more readable to: 1) keep defining a local/private property of shadow: _shadow exactly as you do, but 2) to redefine this private property "_shadow" in the variants, not the global property "shadow" which has been used as a default value. Because it could be not used anymore in the future if the designer decides to use another default value. In this case, the designer would have to **know** that it was used in the variants. You say later in the video that when you use a value, it's better to use the private version, I would also apply this principle to the selector which redefines locally the local values to the *private* properties instead of global ones.
Person reads spec on how css properties work “oh I’ve found a new technique“
Very helpful content
You're the best!
Bro since I started using tailwind a few years ago, watching this video hurts my heart lol… so much more complicated
i tried with sass not working
.cards{
display: flex;
flex-wrap: wrap;
gap: 1em;
$card-bg:red;
$txt-clr:white;
.card{
padding: 1em;
background-color: $card-bg;
h3{
color: $txt-clr;
}
&__red{
$card-bg:red;
$txt-clr:white;
}
&__blue{
$card-bg:blue;
$txt-clr:white;
}
&__green{
$card-bg:green;
$txt-clr:white;
}
&__yellow{
$card-bg:yellow;
$txt-clr:black;
}
}
}
some one please help?
.plan {
--_color: var(--color, red);
--_shadow: hsl(from var(--_color) h s calc(l + .5));
--_icon: hsl(from var(--_color) h s l);
--_button-hover: hsl(from var(--_color) h calc(s + .2) l);
...
}
.plan--pram { --color: yellow }
.plan--bike { --color: cyan }
.plan--rocket { --color: purple }
.plan--light { --color: lime }
;)
I really like the concept of making it possible to make your styles extensible. But there is something that I find annoying I saw you and a lot of others doing: naming variables like --clr-yellow-400, or --clr-blue-300. Just imagine you have to change evething that uses "--clr-yellow-400" to red, for exemple.
You will have 2 options: change the variable content or replacing every usage with another variable named --red-something. Either way you will get a messed code by unrelated name-content or because if you have to replace everything manually anyway, you should have not used a variable in the first place
I have a very simple shell script that let's me do this for a ton of files.
Enter directory to change
Enter a regex to match the files to change
Enter the offending regex: --clr-yellow-400
Enter the new version: --clr-blue-300
Files changed.
Very fast, very easy.
Just change manually the color value and name where it is actually defined first.
One file or two, in your editor.
30 files, use the script. Changing "doog" to "dog" in a whole website in seconds is sooo nice.
@@CrispyCircuits I know there are such features in most ides and some bash scripts. In fact the most "simple" ides, like Notepad++ provides code replacement features by plain text or regexes.
External tools aside, this is still a misunderstanding of variables usage...
This is neat, but it seems trying build a table with just one paint roller. It can paint the surface better, but do poorly cutting woods, drilling holes, or hitting nails.
I use css variables with local overriding. There are more than handful ways to achieve this, and doing everything in CSS doesn't feel right to me.
Why doesn't feel right handle styling problems in the language that is created for handle these problems?
thx for greate info!
Wouldn't this work exactly the same without the underscores?
The idea of private variables in general programming is not to denote locality, but as a "don't use me outside this module". That's how it's used in python, for example, where the _ is just a convention, saying that these could change at any time and won't be marked as a breaking change once a package updates.
Using the same name for an internal variable is called "shadowing" (en.wikipedia.org/wiki/Variable_shadowing) and it's a completely valid approach to the matter.
it's not just a convention, private and public variables are very different things.
@@rossclutterbuck1060 does python have as private keyword now? good to know!! back on python 2 and early days python 3, it was just convention. good stuff!!
that's amazing!
How to have a deep and attractive voice like you using HTML & CSS?