Nested Derived CSS Variable [duplicate] - css

This question already has answers here:
CSS scoped custom property ignored when used to calculate variable in outer scope
(2 answers)
Closed 1 year ago.
I have the following CSS
:root {
--primary: #1776BF;
--header-background-color: var(--primary);
}
header {
--primary: #EA5742;
}
header {
position: fixed;
top: 0;
height: 60px;
left: 0;
right: 0;
background-color: var(--header-background-color); //Expecting it to be #EA5742 but it is still #1776BF
}
As far as I have researched, CSS Variable is not meant to be for this type of case. But still, Is there any way to achieve the expected behavior as I mentioned in the comment line of the above code snippet.

If you want --header-background-color to update is value for header, then you'll have to redeclare that variable too. Just try re-adding --header-background-color: var(--primary); below your second --primary declaration and it will work.
:root {
--primary: #1776BF;
--header-background-color: var(--primary);
}
header {
--primary: #EA5742;
--header-background-color: var(--primary); /* you need to redeclare this variable so that it takes the newly assigned primary value */
}
header {
position: fixed;
top: 0;
height: 60px;
left: 0;
right: 0;
background-color: var(--header-background-color);
}
div { /* this is just an example so you can check the global variable works well too */
position: fixed;
top: 60px;
height: 60px;
left: 0;
right: 0;
background-color: var(--header-background-color);
}
<header>Test</header>
<div>Test</div>

You're right, as var(--xxx) is just replaced by it's value at this time. But why don't you simplify your problematic this way ?
:root {
--primary: #1776BF;
}
body {
background-color: var(--primary);
}
header, anotherelement, yetanotherelement, .aclass {
--primary: #EA5742;
}
header {
position: fixed;
top: 0;
height: 60px;
left: 0;
right: 0;
background-color: var(--primary);
}
<header>test</header>

Related

Angular CSS class names collide with other components after Material Theming

Hey there I've read many things about the style scopes for example https://angular.io/guide/component-styles. And somehow the point
Class names and selectors are local to the component and don't collide
with classes and selectors used elsewhere in the application.
does not work for me.
I have a header-component with the css class profileImage. Then there's also the class profileImage in my user-component. I'm not using any custom encapsulation for any component. But still it's buggy now because the class profileImage of the user-component also uses the one of the header-component and only overrides the elements defined in both. So for example position: absolute; gets inherited but it should not.
.profileImage[_ngcontent-bkm-c17] { //user-component
max-width: 34px;
max-height: 34px;
width: auto;
height: auto;
margin: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.profileImage { //header-component
border-radius: 50%;
position: absolute;
max-width: 54px;
max-height: 54px;
width: auto;
height: auto;
margin: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
This happend after using angular theming. To explain what exactly is forcing this problem:
I got a component-themes.scss:
#import "./app/header/header.component";
#mixin component-themes($theme) {
#include tile-theme($theme);
}
It's included in my material-themes.scss:
#include angular-material-theme($theme);
#include component-themes($theme);
.dark-theme {
color: $light-primary-text;
$dark-primary: mat-palette($mat-grey, 700, 300, 900);
$dark-accent: mat-palette($mat-blue-grey, 400);
$dark-warn: mat-palette($mat-red, 500);
$dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn);
#include angular-material-theme($dark-theme);
#include component-themes($dark-theme);
}
And this is used in the basic styles.scss.
How can I prevent the described behavior while using component-themes?
The following code is for a mat-menu not a tile. I haven't renamed it yet because it's a copy of a tutorial.
header-component.scss (requested):
#import "~#angular/material/theming";
#mixin tile-theme($theme) {
$primary: map-get($theme, primary);
$background: map-get($theme, background);
$background-color: mat-color($background, card);
.tile {
background-color: mat-color($primary);
}
}
.toolbar-spacer {
flex: 1 1 auto;
}
// verantwortlich für das Layout der Toolbar
.startpage:hover {
opacity: 0.6;
}
.mat-toolbar {
height: 7vh;
}
div {
overflow: inherit;
}
.language-buttons {
padding: 0 25px;
margin-right: 32px;
}
.language-buttons-login {
padding: 0 20px;
}
.navigate-buttons {
padding: 0 12px;
}
.mat-fab.mat-accent {
background: #3f51b5;
}
::ng-deep .mat-menu-panel {
position: relative;
top: 5px;
right: -16px;
}
.mat-button,
.mat-flat-button,
.mat-icon-button,
.mat-stroked-button {
min-width: 1px;
}
.imageContainer {
width: 54px;
height: 54px;
right: 20px;
position: absolute;
}
.profileImage {
border-radius: 50%;
position: absolute;
max-width: 54px;
max-height: 54px;
width: auto;
height: auto;
margin: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.font-awesome {
margin-right: 19px;
}
// ::ng-deep .accent-tooltip {
// background-color: mat-color($accentPalette);
// }
You are importing your "./app/header/header.component"; inside the component-theme.scss. This leads to the result that all styles from header.component will be global, because you are using the material-themes.scss in your global styles.scss.
So all styles you defined in header.component.scss will be loaded global, without that the angular compiler adds special attributes to ensure encapsulation. This leads to the result that other components, with the same classes will inherit all properties.
UPDATE:
Original answer proposed to simply remove the #import header.component statement, but after OP added the header.component implementation it was obvious that this would not be sufficient.
To solve this the best solution would be to replace the #import rule with the #use rule. But as this feature is currently only included in DartSass and only since version 1.23.0, another solution is to remove the mixin definition from the header.component.scss file and move it directly to the component-theme.scss, and remove the #import rule.

What's the right way of combining CSS multiple pseudo-elements?

I have created a code for a page following Stackoverflow answers. It works very well, but I'd like to optimize it, which I do not know since I'm not a programmer. What is the right way?
#black:before {
content: "";
position: fixed;
top: 0;
right: 0; left: 0; bottom: 0; background: none;
z-index: -2;}
#red:before {
content: "";
position: fixed;
top: 0;
right: 0; left: 0; bottom: 0; background: none;
z-index: -2;}
#black:target::before {background: #ACAA92;}
#red:target::before {background: #ACAA92;}
#black:hover .text{display:block;}
#com:hover .text{display:block;}
All selectors which should share the same properties and values can simply be comma separated. You can write them all on one line though a more preferred style is to put each one its own line to aid readability:
#black:target::before, #red:target::before { background: #ACAA92; }
#black:hover .text,
#com:hover .text {
display:block;
}
https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS/Combinators_and_multiple_selectors#Groups_of_selectors_on_one_rule

How can I make a full width videojs v5 progress bar?

I would like to change the videojs v5 controls layout in order to make a full width progress bar, on top of the vjs-control-bar area, similar to the pre-v5 player skin.
Here is the v5 skin:
And here is the pre-v5 skin. Notice the full width progress bar:
How should I proceed? Is it necessary to modify the component structure tree within the ProgressControl component or can it be done using CSS only, with the existing ProgressControl component?
I noticed that I can put it on top by changing the vjs-progress-control display CSS property from flex to block, initial or inline but I can't set the width to 100% (other ProgressControl components width are still considered). I assume it is because the vjs-progress-control is still in the flex flow of the container.
EDIT
I made some progress. I can achieve the desired effect by using the following CSS:
.vjs-progress-control {
position: absolute;
bottom: 26px; /* The height of the ControlBar minus 4px. */
left: 0;
right: 0;
width: 100%;
height: 10px; /* the height must be reduced from 30 to 10px in order to allow the buttons below (e.g. play) to be pushed */
}
.vjs-progress-holder {/* needed to have a real 100% width display. */
margin-left: 0px;
margin-right: 0px;
}
Unless one of you find a way to make it better, I will post this edit as accepted answer when it will be allowed.
DEMO
.vjs-fluid {
overflow: hidden;
}
.vjs-control-bar {
display: block;
}
.vjs-control {
position: absolute;
}
.vjs-progress-control {
bottom: 28px; left: 0;
height: 10px;
width: 100%;
}
.vjs-progress-holder {
position: absolute;
left: 0; margin: 0;
height: 8px; width: 100%;
}
.vjs-play-progress,
.vjs-load-progress {
height: 8px;
}
.vjs-play-progress:before {
font-size: 12px; top: -2px;
text-shadow: 0 0 2px black
}
.vjs-current-time {
display: block;
left: 35px;
}
.vjs-time-divider {
position: absolute;
display: block;
left: 70px;
}
.vjs-remaining-time {
display: none;
}
.vjs-duration {
display: block;
left: 70px;
}
.vjs-volume-menu-button {
position: absolute;
bottom: 0; right: 55px;
}
.vjs-playback-rate {
position: absolute;
bottom: 0; right: 28px;
}
.vjs-fullscreen-control {
position: absolute;
bottom: 0; right: 0;
}
There's still need to style the subtitles, captions and chapter buttons
.video-js .vjs-progress-control {
position:absolute;
width: 100%;
top:-.3em;
height:3px;
/* deal with resulting gap between progress control and control bar that
is the result of the attempt to keep things "clickable" on the controls */
background-color: #2B333F;
background-color: rgba(43, 51, 63, 0.7);
}
.video-js .vjs-progress-holder {
position:absolute;
margin:0px;
top:0%;
width:100%;
}
This seemed to get rid of the problems I had across other browsers with the :hover styling inherited from video.js. More masterful css developers might be able to make the expansion a bottom-to-top expansion, negating the need for the fancy footwork around the position of the progress control and the color.
Here is a minimal custom skin (in scss) that shows a full-width progress bar above the rest of the controls. This works with video.js 5.19.2
.video-js.vjs-custom-skin {
.vjs-custom-control-spacer {
display: flex;
flex: 1 1 auto;
}
.vjs-time-divider {
display: inherit;
}
.vjs-current-time {
margin-left: 1em;
}
.vjs-current-time, .vjs-duration {
display: inherit;
padding: 0;
}
.vjs-remaining-time {
display: none;
}
.vjs-play-progress:before {
display: none;
}
.vjs-progress-control {
position: absolute;
left: 0;
right: 0;
width: 100%;
height: .5em;
top: -.5em;
&:hover {
height: 1.5em;
top: -1.5em;
}
}
.vjs-progress-holder {
margin: 0;
height: 100%;
}
}

How to combine the ::after and :not pseudo selectors

I have the following SASS code:
section.post {
a {
transition: all $aside-animation-time;
&::after {
position: absolute;
bottom: -.5px;
left: 0;
width: 100%;
height: 0;
content: '';
border-bottom: 1px solid $primary-color;
}
&:hover {
border-color: $hover-color;
}
}
}
What I'm doing here is adding a blue bottom border for all links. However, I noticed that when I use anchor tags with images inside, the image also has the border (since it's a link as well). Now, my goal is to append the anchor styles to text links only.
What I tried so far is using :not(img), chaining it with ::after, overriding the previous rules etc., but nothing worked as expected. Any help would be appreciated.
Currently CSS doesn't have an option to style the parent based on any child elements. If you were styling the image itself with the link it would be fine.
You might be able to use something like jQuery to add a class to any links which contain child images:
$('a:has(img)').addClass('has_img');
You can then use this with your CSS :not as in
section.post {
a:not(.has_img) {
transition: all $aside-animation-time;
&::after {
position: absolute;
bottom: -.5px;
left: 0;
width: 100%;
height: 0;
content: '';
border-bottom: 1px solid $primary-color;
}
&:hover {
border-color: $hover-color;
}
}
}
Maybe this will help you.
a {
display: block;
height: 2.5em;
position: relative;
&:after {
border-bottom: thin solid blue;
bottom: 0;
content: '';
left: 0;
position: absolute;
width: 100%;
}
&:hover:after {
border-bottom-color: red;
}
img {
display: block;
height: inherit;
position: relative;
z-index: 1;
}
}
Quick Codepen sample:
http://codepen.io/vkjgr/pen/WvMGRK

class wildcards in CSS Parse Error 'div.*{'

I noticed that I have a lot of repeated code in my divs and that some people had:
* {
padding: 0;
border: 0;
margin: 0;
}
That effects all elements including headings and paragraphs so I tried:
div.* {
position: relative;
padding: 0;
border: 0;
margin: 0;
}
Which is not working right and is showing up as a Parse Error in the w3c validator.
What is the correct wildcard for a class?
Are you trying to match any div element that has a class, whatever that class may be?
If so, use an attribute selector:
div[class] {
position: relative;
padding: 0;
border: 0;
margin: 0;
}
Or are you just looking for any div element?
Then simply use div:
div {
position: relative;
padding: 0;
border: 0;
margin: 0;
}

Resources