Can you, and if so how do you, undo a css specification? Suppose you wanted
textarea { width: 500px; }
and then you want a specific textarea with 70 columns:
<textarea class='email' cols=70></textarea>
Ideally, I would write a css rule
textarea.email { width: revert_to_default_unspecified_value; }
(but obviously that value doesn't exist.)
How do you do this? I'm interested in both this specific case, and also how to undo parent css specifications in children. This must have been talked about plenty, but it's hard to google.
The default value you're looking for is:
Initial: auto
http://www.w3.org/TR/CSS2/visudet.html#the-width-property
Notice that setting auto will revert to default for just some of the CSS properties. Other have different initial values.
The background-color property, for example, has a default value of transparent.
Initial: transparent
http://www.w3.org/TR/CSS2/colors.html#background
Some of the properties, like color, can't be restored to a default because they don't have a known default.
Initial: depends on user agent
http://www.w3.org/TR/CSS2/colors.html#colors
About undoing inherited CSS in children.
Let's take the font-size property, a property that inherits.
level0
<div style="font-size:36px;">
level1
<div [style="font-size:medium;"]>
level2
</div>
</div>
By default the level2 font size would be inherited from level1, but if we add the initial medium value we reset it to the size of the level0 text. The only inconvenient is that we can't ignore just one level of inheritance, so if we would add a level3, we would still be resetting to level0, and not level1.
textarea.email { width: auto; }
I would assume that since if you do not specify a css width rule at all for this textarea, its default value would be width: auto. Thus I would try in the specific case setting it back to the default where the HTML attributes should take over as normal:
textarea.email { width: auto }
To reset styles you can now use unset and initial special properties. The support for unset is currently low (56%) -http://caniuse.com/#search=CSS%20unset%20value but support for initial is quite high (80%) - http://caniuse.com/#search=CSS%20initial%20value.
Consider the example:
http://codepen.io/anon/pen/OMROye
<div class="outer">
Foo
<div class="middle">
Bar
<div class="inner">
Baz
</div>
</div>
</div>
.outer {
font-size: 50px;
color: #f3f;
}
.middle {
font-size: 25px;
color: #33f;
}
.inner {
font-size: 15px;
color: #f33;
}
.inner {
font-size: unset;
color: unset;
}
The inner text will have font-size and color like its' parent.
If we change our last style to:
.inner {
font-size: initial;
color: initial;
}
The inner text will have standard color and standard font-size.
Now it is the best time to point out that these properties are a little trickier than they look, for example unset sometimes acts like initial and sometimes acts like inherit.
Links to docs:
https://developer.mozilla.org/en-US/docs/Web/CSS/initial
https://developer.mozilla.org/en-US/docs/Web/CSS/unset
https://developer.mozilla.org/en-US/docs/Web/CSS/initial_value
Related
I'm not sure how to explain this if not with examples.
Let's say I have this class
.padding1 {
padding-top: 100px;
}
applied to this element
<div class="myDiv padding1"></div>
whith its own rules defined later that will override the .padding1 rule. How to tell .myDiv to default to the last useful rule defined in .padding1?
.myDiv {
padding-top: 0;
}
.specialPage .myDiv {
padding-top: /* ignore my override */
}
I know I could do it the opposite way but I was wondering if this can be done in this way instead which can be useful in some complex designs.
UPDATE: I was of course asking to see if there's a rule I'm missing. I don't want to declare it again, nor use initial or inherit.
I just found out about this, there is a possible way to revert css styles using revert-layer.
⚠ Warning ⚠ : As of 2022, this keyword is experimental and not widely compatible. Currently only for Firefox and Firefox Android v97.
The revert-layer CSS keyword rolls back the value of a property in a cascade layer to the value of the property in a CSS rule matching the element in a previous cascade layer.
If there is no other cascade layer to revert to for the matching CSS rule, the property value rolls back to the computed value derived from the current layer. Furthermore, if there is no matching CSS rule in the current layer, the property value for the element rolls back to the style defined in a previous style origin.
Different from the revert keyword which reverts directly to the browser's defaults.
Additional ressources:
Creating layers with #layer
Style origin. Used to determine where to stop rolling back the cascade of styles
The following should work (Again, if your browser is compatible)
Elements with class 'padding1' will have a padding-top of 100px, unless they also have the class 'myDiv' in which case the padding will be set back to 0, but if said element is inside a parent with class 'specialPage', the padding will be reverted back to 100px.
#layer base {
.padding1 {
padding-top: 100px;
}
}
#layer special {
.myDiv {
padding-top: 0;
}
.specialPage .myDiv {
padding-top: revert-layer;
}
}
<div class="specialPage">
<div class="myDiv padding1">Inside specialPage original padding</div>
</div>
<div class="myDiv padding1">Outside specialPage no padding</div>
You can use padding-top: unset; which would completely neutralize all previous properties of the same name for the same class. But in order to "rewind" the property that came before padding-top: 0; you need to declare it again.
As I understand, You want style of .padding1 to be implemented for both div. Am I right?
This can be done like this
<style>
.padding1{
padding-top: 100px !important;
}
.myDiv {
padding-top: 0;
}
<style>
In HTML page
<div class="myDiv padding1"></div>
Now .myDiv will have padding-top:100px;
As .myDiv have own "padding-top:0" but it will show "padding-top:100px".
Hope it will solve you problem.
You could use initial to set it to its default value.
.myDiv {
padding-top: 0;
}
.padding1 {
padding-top: 100px;
}
.specialPage .myDiv {
padding-top: initial;
}
I came across this problem while handling a large project and felt that i should seek an opinion from the community here.
I have specified a css class 'header' in style1.css, i.e.
.header { color: red;}
In another file, I inadvertently, named a class 'header' again with this rule :
.header { background-color: yellow; }
When i refreshed the browser i noticed the red font and after examining the style inspector found the problem. I tried to avoid the problem by applying specificity, i.e. #some-div .header, but that didnt stop it from applying the red font. Of course i could simply solve the problem by renaming header to something else, but i'm curious how developers who handle large projects handle this. Thanks for your time.
Well, from your code, you specified values for different properties in the two declarations of the header class. The first declaration specifies a color property and the second specifies a background-color property. From all indications you're not really "overriding" anything since you didn't give conflicting values for one property so, CSS is simply giving the values of the first declaration of the header class to the second one because there's no difference. If you wanted to override it for the second you'd have to probably add a different identifier to the second declaration of the header class to point to a unique element and specify a different value for the color property. Hope this satisfied your curiosity.
Just add a different class to one of the cases. For example:
.header {
color: red;
}
.header.yellow-bg {
color: initial;
background-color: yellow;
}
<h3 class="header">Red header</h3>
<h3 class="header yellow-bg">Black/yellow header</h3>
The second declaration for color applies because it is more specific (2 classes > 1 class).
Don't use !important as another user suggested. Avoid it all costs. It's the easy way out for the moment, but once you start going down that road, you're going to end up with a stylesheet that's terrible to manage.
Set your styles for a specific base and use classes and more specific selectors as overrides. Remember that stylesheets cascade.
For example, say you have a typical header font color that should be your .header. If you have other one-off or unique headers that share same structure provide another class to that which makes sense to you.
So as an example:
Both headers have the .header styles but headers with the special class have blue text color which overrides red.
.header {
color: red;
width: 100%;
display: block;
background-color: #eee;
padding: 10px;
margin: 2px;
}
.header.special {
color: blue;
}
<div class="header">Regular Header</div>
<div class="special header">Special Header</div>
I'm creating a chat widget and I want to overwrite a bunch of CSS. For example if this is the website theme's CSS:
textarea {
color: red;
margin: 10px;
}
and if I style my widget like:
textarea {
padding: 5px;
}
then only my widget's CSS should work. However, it adds both CSSs to textarea by default - how can I prevent the website's CSS from being added?
As Marc B stated, you can put your chat in an iframe, in which case you can have its own completely separate stylesheet.
If you must use it inline, then you can use all css property to unset what has been set elsewhere:
Widget CSS:
textarea {
all: unset;
padding: 5px;
}
Further, as pointed out in comments elsewhere, the best way is to create different classes for text area and use them where necessary, for example:
textarea.main {
color: red;
margin: 10px;
}
and if I style my widget like:
textarea.chat {
padding: 5px;
}
And then use
<textarea class="main">
or
<textarea class="chat">
depending on what you need.
Well I guess it is really easy to write !important to all your css rules. Just replace ";" with "!important" if that's an easy way for you OR if you really want to change then you can use iframe really
I'm curious to the behaviour of using calc() in setting a CSS variable.
Example:
#test {
--halfWidth: calc(100% / 2);
}
Now, if the #test element, say a div, was 500px wide, I would like the --halfWidth variable to be set to 250px.
But, as far as I can tell the var(--halfWidth) code used elsewhere simply drops in the calc(100% / 2) string instead of 250px. Which means that I can't use the calculation of say element A and use it in element B later on, since it would simply set for example width: var(--halfWidth); as half the width of element B instead of half the width of element A, where the variable was defined.
I've scoured the web trying to find any documentation on the behaviour of this, but I have so far drawn a blank.
Ideally, setting a CSS variable using calc should be available in two variants:
One variant working just like this example, simply dropping in the string as-is, bar any in-string variable replacements.
A second variant where calc() would yield the result of the calculation instead of simply replacing the string.
How to achieve this? I'd rather leave the actual implementation to people suited to it, but one possibility would be an eval() kind of thing; like eval(calc(100% / 2)) would give the result 250px.
Anyway, if anyone have any real documentation on this behaviour or a solution to how to get the example above to yield the result instead, I'm all ears!
Edit: Just FYI, I have read the specs at https://drafts.csswg.org/css-variables/
This is kind of a tough question to answer cause the answer will not be:
Do it like this...then it will work
The problem you are facing is the normal behavior of CSS. It cascades the styles. If what you are trying to achieve would work it would get real messy after a short amount of time.
I mean how cool is it that you can define a variable like this
#test {
--halfWidth: calc(100% / 2);
}
where var(--halfWidth) should always be calc(100% / 2). Did you note that it will always be half the width of the parent element?
Imagine how strange it would be if a programmer in a few months reads your code and has box with a width of 1000px set with --halfWidth and now it is 250px wide ... I would think the internet is broken :) It should just be 500px wide.
To achieve what you want, you could/should define different vars defining the widths of the parent elements. And split it down to the children.
One approach to this is to dynamically add a line to the CSS Object Model (CSSOM) which explicitly declares the width of the .halfwidth class.
This width will then apply to all divs with the .halfwidth class.
In the example below, I have, additionally, made .element-a horizontally resizable, so that you can see more clearly that as you change the width of .element-a, the width of both .halfwidth divs changes proportionately, including the .halfwidth div which is a child of .element-b.
Working Example:
let myStylesheet = document.styleSheets[0];
const elementA = document.getElementsByClassName('element-a')[0];
let elementAWidth = window.getComputedStyle(elementA).getPropertyValue('width');
const calculateHalfWidth = (elementAWidth) => {
myStylesheet.insertRule('.halfWidth { width: ' + (parseInt(elementAWidth) / 2) + 'px; }', myStylesheet.cssRules.length);
}
calculateHalfWidth(elementAWidth);
// ================================================================================
// THE SCRIPT BELOW USES A ResizeObserver TO WATCH THE RESIZABLE .element-a DIV
// ================================================================================
const elementAObserver = new ResizeObserver(entries => {
for (let entry of entries) {
if (entry.contentRect.width !== elementAWidth) {
calculateHalfWidth(entry.contentRect.width);
}
}
});
elementAObserver.observe(elementA);
body {
font-family: sans-serif;
}
div.element {
float: left;
width: 200px;
height: 100px;
margin: 12px 3px;
text-align: center;
border: 1px solid rgb(0, 0, 0);
}
div.element h2 {
font-size: 18px;
}
div.element-a {
resize: horizontal;
overflow: auto;
}
div.element-b {
width: 300px;
}
div.halfWidth {
height: 40px;
margin: 0 auto;
border: 1px dashed rgb(255, 0, 0);
}
div.halfWidth h2 {
font-size: 14px;
}
<div class="element element-a">
<h2>Element A</h2>
<div class="halfWidth">
<h2>halfWidth</h2>
</div>
</div>
<div class="element element-b">
<h2>Element B</h2>
<div class="halfWidth">
<h2>halfWidth</h2>
</div>
</div>
I look on Stack Overflow, and didn't find the solution, I know how to override style if style exists, just change its property. But now I have a strange style to override
Here is an example of what I have
First I have this one:
.slikezamenjanje img{
max-width: 100%;
max-height:150px;
padding-right:7px;
}
Now I need to override that style with just this one:
#zoomTarget .slikezamenjanje img {
max-width: 100%;
}
The problem is that first style appends second, but I don't want that, in this second style what I need is just one line, not to append from the first style?
Instead of override you can add another class to the element and then you have an extra abilities.
for example:
HTML
<div class="style1 style2"></div>
CSS
//only style for the first stylesheet
.style1 {
width: 100%;
}
//only style for second stylesheet
.style2 {
width: 50%;
}
//override all
.style1.style2 {
width: 70%;
}
You just have to reset the values you don't want to their defaults. No need to get into a mess by using !important.
#zoomTarget .slikezamenjanje img {
max-height: auto;
padding-right: 0px;
}
Hatting
I think the key datum you are missing is that CSS comes with default values. If you want to override a value, set it back to its default, which you can look up.
For example, all CSS height and width attributes default to auto.