ChatGPT解决这个技术问题 Extra ChatGPT

Can a CSS class inherit one or more other classes?

css

Is it possible to make a CSS class that "inherits" from another CSS class (or more than one).

For example, say we had:

.something { display:inline }
.else      { background:red }

What I'd like to do is something like this:

.composite 
{
   .something;
   .else
}

where the ".composite" class would both display inline and have a red background

think more about cascading rather than inheritance, it doesn't apply here

C
CoderPi

There are tools like LESS, which allow you to compose CSS at a higher level of abstraction similar to what you describe.

Less calls these "Mixins"

Instead of

/* CSS */
#header {
  -moz-border-radius: 8px;
  -webkit-border-radius: 8px;
  border-radius: 8px;
}

#footer {
  -moz-border-radius: 8px;
  -webkit-border-radius: 8px;
  border-radius: 8px;
}

You could say

/* LESS */
.rounded_corners {
  -moz-border-radius: 8px;
  -webkit-border-radius: 8px;
  border-radius: 8px;
}

#header {
  .rounded_corners;
}

#footer {
  .rounded_corners;
}

wow, LESS is pretty much exactly what I'm looking for ... it's a shame that it's not supported natively, and that it's written in Ruby (I'm using ASP.NET MVC)
Yeah, I'm in the ASP.NET world too so I haven't moved it into my production workflow.
Yeah LESS is pretty sweet isn't it. Ive actually been working on a .NET port here: nlesscss.codeplex.com.
in case you reach this via google: the .Net port is now here
Instead of LESS you can use SCSS/SASS: sass-lang.com/guide . E.g. like the answer: stackoverflow.com/a/22770378/1742529 .
k
kxr

You can add multiple classes to a single DOM element, e.g.

<div class="firstClass secondClass thirdclass fourthclass"></div>

Rules given in later classes (or which are more specific) override. So the fourthclass in that example kind of prevails.

Inheritance is not part of the CSS standard.


do you know if which class prevail, the last ones or the 1st ones and is the behaviour cross browser safe? Let's say we have .firstClass {font-size:12px;} .secondClass {font-size:20px;} will then final font-size be 12px or 20px and is this cross browser safe?
The rule with the highest specificity on the selector will win. Standard specificity rules apply; in your example, since "first" and "second" have the same specificity, the rule declared later in the CSS will win.
I like the idea of using pure CSS (instead of LESS) to solve this issue.
I also like the idea of not typing out multiple classes multiple times - Which is O(n^2) work :)
What if I am using a third party lib and want to modify the design/HTML it provides, but can't change the inbuilt css files in that lib ? There I would need some kind of inheritance in css classes.
C
CoderPi

Yes, but not exactly with that syntax.

.composite,
.something { display:inline }

.composite,
.else      { background:red }

This suck, but I'm glad that we at least have this!
Why it sucks? it seem very good. I can't understand the difference between the comma symbol and the less.js solution.
Because if the .something and the .else classes are in different files and that you cannot modify them, then you're stuck.
This was the right answer because it answered the question using pure CSS syntax. The less answer is good to know though.
Other drawback of this solution, though it's quite nice as a puzzle solution that the hole CSS code could quickly became intractable, because one can't organize classes logically e.g. we want .else's and .something's definition to place into quite other groups of CSS definitions.
C
CoderPi

Keep your common attributes together and assign specific (or override) attributes again.

/*  ------------------------------------------------------------------------------ */   
/*  Headings */ 
/*  ------------------------------------------------------------------------------ */   
h1, h2, h3, h4
{
    font-family         : myfind-bold;
    color               : #4C4C4C;
    display:inline-block;
    width:900px;
    text-align:left;
    background-image: linear-gradient(0,   #F4F4F4, #FEFEFE);/* IE6 & IE7 */
}

h1  
{
    font-size           : 300%;
    padding             : 45px 40px 45px 0px;
}

h2
{
    font-size           : 200%;
    padding             : 30px 25px 30px 0px;
}

This is very close to an ideal solution, I hope people won't discard it just because it got few votes. In fact, one of the most challenging issues about "CSS inheritance" is that you usually get an already made, huge web software (in example, an e-commerce or a blog PHP famous software) and they employ PHP code that natively won't add multiple classes to the HTML elements they outuput. This forces you to go around and mess with source code (losing changes if you upgrade later) to make it output those additinal classes. With this approach, instead, you only ever edit the CSS file!
This was exactly what I was looking for. Is it worth nothing this same approach will work with CSS Selectors? Instead of specifying h1, h2, etc you could specify .selector1, .selector2, .etc
I wanted to comment that this is precisely the approach used by w3 in their recommended default html style sheet: [w3 CSS2]: w3.org/TR/CSS2/sample.html. I'm also trying to get a grip on how to organize css code, and it seems like the paradigm is inverted compared to typical object-oriented inheritance: you use classes (or, more generally selectors) to specify which elements inherit which attributes, but you inherit attributes (at least, this is how the hierarchy can most easily exist logically), then override attributes at the more specific selectors when necessary.
FYI on my downvote: this is normal CSS using element selectors, it doesn't use a single CSS class. I don't want to be rude, but just FYI that my reading of this answer should not be called an example of class inheritance. If the goal was to teach basic CSS principals I would upvote, but it is not an answer the OP question, so downvote.
This is not the way libraries like Bootstrap are constructed, and a CSS mixin, which does not exist, seems to be the only way to extend a Bootstrap class to always include the properties of another Bootstrap class, so all the "class" attributes throughout a website don't have to be changed.
P
Pete

An element can take multiple classes:

.classOne { font-weight: bold; }
.classTwo { font-famiy:  verdana; }

<div class="classOne classTwo">
  <p>I'm bold and verdana.</p>
</div>

And that's about as close as you're going to get unfortunately. I'd love to see this feature, along with class-aliases someday.


C
CoderPi

No you can't do something like

.composite 
{
   .something;
   .else
}

This are no "class" names in the OO sense. .something and .else are just selectors nothing more.

But you can either specify two classes on an element

<div class="something else">...</div>

or you might look into another form of inheritance

.foo {
  background-color: white;
  color: black;
}

.bar {
  background-color: inherit;
  color: inherit;
  font-weight: normal;
}
<div class="foo">
  <p class="bar">Hello, world</p>
</div>

Where the paragraphs backgroundcolor and color are inherited from the settings in the enclosing div which is .foo styled. You might have to check the exact W3C specification. inherit is default for most properties anyway but not for all.


yup, this (first part) was my expectation when i first heard of CSS back in 20th century... and we still do not have it, they are burning performance on some dynamic things while this can be static composed just before the css apply and it replaces the need of variables (static "variables")
I
Igor Ivancha

The SCSS way for the given example, would be something like:

.something {
  display: inline
}
.else {
  background: red
}

.composite {
  @extend .something;
  @extend .else;
}

More info, check the sass basics


What is the added value compared to this? .composite,.something { display:inline } and .composite,.else { background:red }
@PavelGatnar You could reuse the definitions of .something and .else in another css definitions.
D
DHoover

I ran into this same problem and ended up using a JQuery solution to make it seem like a class can inherit other classes.

<script>
    $(function(){
            $(".composite").addClass("something else");
        });
</script>

This will find all elements with the class "composite" and add the classes "something" and "else" to the elements. So something like <div class="composite">...</div> will end up like so:
<div class="composite something else">...</div>


The problem with this solution is that applies to all the existing controls, if you create the control after this call, it won't have the new class.
T
Tomer W

You can do is this

CSS

.car {
  font-weight: bold;
}
.benz {
  background-color: blue;
}
.toyota {
  background-color: white;
}

HTML

<div class="car benz">
  <p>I'm bold and blue.</p>
</div>
<div class="car toyota">
  <p>I'm bold and white.</p>
</div>

C
CoderPi

Don't forget:

div.something.else {

    // will only style a div with both, not just one or the other

}

im not looking for it, but this was constructive for me n__n
C
CoderPi

Perfect timing: I went from this question to my email, to find an article about Less, a Ruby library that among other things does this:

Since super looks just like footer, but with a different font, I'll use Less's class inclusion technique (they call it a mixin) to tell it to include these declarations too:

#super {
  #footer;
  font-family: cursive;
}

Just when I thought LESS couldn't surprise me any more... I had no idea you could import formatting from another block like this. Great tip.
C
CoderPi

In Css file:

p.Title 
{
  font-family: Arial;
  font-size: 16px;
}

p.SubTitle p.Title
{
   font-size: 12px;
}

So what will be the resulting font-size?
The font size would be 12px for "p.Title" because it is defined after the first one in the file. it overrides the first font-size.
@YWE: Does that mean the declarations should actually be the other way round compared to what is written in this answer (at least if we want to example to be illustrative)? If the last one defined prevails, the font-size: 16px can never take effect, right?
@O.R.Mapper - typically what happens is that the first declaration is in a common css file, that is shared by multiple pages. Then the second declaration is in a second css file, used only on certain pages. And imported after the common css file. So those pages use the "last seen" value of 12px.
J
John Carrell

I realize this question is now very old but, here goes nothin!

If the intent is to add a single class that implies the properties of multiple classes, as a native solution, I would recommend using JavaScript/jQuery (jQuery is really not necessary but certainly useful)

If you have, for instance .umbrellaClass that "inherits" from .baseClass1 and .baseClass2 you could have some JavaScript that fires on ready.

$(".umbrellaClass").addClass("baseClass1");
$(".umbrellaClass").addClass("baseClass2");

Now all elements of .umbrellaClass will have all the properties of both .baseClasss. Note that, like OOP inheritance, .umbrellaClass may or may not have its own properties.

The only caveat here is to consider whether there are elements being dynamically created that won't exist when this code fires, but there are simple ways around that as well.

Sucks css doesn't have native inheritance, though.


This approach has already been suggested in @DHoover's answer from 2013.
Needs the plain JavaScript code. It is possible to locate and extract class rules from a library stylesheet and append them to another library or custom stylesheet or rule, but there doesn't seem to be an example on the Web and the code to do it right is a bit complex. I could not design a function to merge class rules after about an hour of work.
C
CSSBurner

You can use the converse approach to achieve the same result - start from the composite and then remove styling using the unset keyword. For example, if you start with the following sample composition:

.composite {
    color: red;
    margin-left: 50px;
    background-color: green
}

you can then increase selector specificity to selectively remove styles using unset:

.composite.no-color {
    color: unset
}

.composite.no-margin-left {
    margin-left: unset
}

.composite.no-background-color {
    background-color: unset
}

Here is a JSFiddle demonstrating this approach.

One benefit of this approach is that because the specificity of the compound selectors is higher than the composite itself, you do not need all of the combinations of classes to achieve the desired results for multiple combinations:

/* Multi-unset compound selector combinations, such as the one that follows, ARE NOT NECESSARY because of the higher specificity of each individual compound selectors listed above. This keeps things simple. */
.composite.no-background-color.no-color.no-margin-left {
    background-color: unset;
    color: unset;
    margin-left: unset
}

Furthermore, at 96% support for the unset keyword, browser coverage is excellent.


I think this is the best answer by far It could be improved specifying the element type at the beginning e.g. div.composite.no-background-color.no-color.no-margin-left {...}
L
LBushkin

Unfortunately, CSS does not provide 'inheritance' in the way that programming languages like C++, C# or Java do. You can't declare a CSS class an then extend it with another CSS class.

However, you can apply more than a single class to an tag in your markup ... in which case there is a sophisticated set of rules that determine which actual styles will get applied by the browser.

<span class="styleA styleB"> ... </span>

CSS will look for all the styles that can be applied based on what your markup, and combine the CSS styles from those multiple rules together.

Typically, the styles are merged, but when conflicts arise, the later declared style will generally win (unless the !important attribute is specified on one of the styles, in which case that wins). Also, styles applied directly to an HTML element take precedence over CSS class styles.


Your answer came up as first result on google for me and was helpful. That said, I have a tip for you - if you are offering a solution, it is best to avoid starting sentences negatively (Unfortunately, CSS does not provide inheritance..) I know anyone with suitable patience would read on to discover your nice solution but sometimes people are running low on patience and may rush into a conclusion that what they are trying to do is impossible. For the best chance of helping others, you could start with something like "Whilst CSS does not have inheritance, you can achieve what you need to by..."
N
Nathan Chappell

Don't think of css classes as object oriented classes, think of them as merely a tool among other selectors to specify which attribute classes an html element is styled by. Think of everything between the braces as the attribute class, and selectors on the left-hand side tell the elements they select to inherit attributes from the attribute class. Example:

.foo, .bar { font-weight : bold; font-size : 2em; /* attribute class A */}
.foo { color : green; /* attribute class B */}

When an element is given the attribute class="foo", it is useful to think of it not as inheriting attributes from class .foo, but from attribute class A and attribute class B. I.e., the inheritance graph is one level deep, with elements deriving from attribute classes, and the selectors specifying where the edges go, and determining precedence when there are competing attributes (similar to method resolution order).

https://i.stack.imgur.com/GyXys.png

The practical implication for programming is this. Say you have the style sheet given above, and want to add a new class .baz, where it should have the same font-size as .foo. The naive solution would be this:

.foo, .bar { font-weight : bold; font-size : 2em; /* attribute class A */}
.foo { color : green; /* attribute class B */}
.baz { font-size : 2em; /* attribute class C, hidden dependency! */}

https://i.stack.imgur.com/iHIFf.png

Any time I have to type something twice I get so mad! Not only do I have to write it twice, now I have no way of programatically indicating that .foo and .baz should have the same font-size, and I've created a hidden dependency! My above paradigm would suggest that I should abstract out the font-size attribute from attribute class A:

.foo, .bar, .baz { font-size : 2em; /* attribute base class for A */}
.foo, .bar { font-weight : bold; /* attribute class A */}
.foo { color : green; /* attribute class B */}

https://i.stack.imgur.com/27RKo.png

The main complaint here is that now I have to retype every selector from attribute class A again to specify that the elements they should select should also inherit attributes from attribute base class A. Still, the alternatives are to have to remember to edit every attribute class where there are hidden dependencies each time something changes, or to use a third party tool. The first option makes god laugh, the second makes me want to kill myself.


C
CoderPi

That's not possible in CSS.

The only thing supported in CSS is being more specific than another rule:

span { display:inline }
span.myclass { background: red }

A span with class "myclass" will have both properties.

Another way is by specifying two classes:

<div class="something else">...</div>

The style of "else" will override (or add) the style of "something"


For all styles in 1 file there is an inheritance-like solution in CSS, see my post.
A
Assaf Lavie

As others have said, you can add multiple classes to an element.

But that's not really the point. I get your question about inheritance. The real point is that inheritance in CSS is done not through classes, but through element hierarchies. So to model inherited traits you need to apply them to different levels of elements in the DOM.


It is better to create inheritance-like CSS definitions instead of using all the composition class chain, see my post.
S
Stryderunknown

While direct inheritance isn't possible.

It is possible to use a class (or id) for a parent tag and then use CSS combinators to alter child tag behaviour from it's heirarchy.

p.test{background-color:rgba(55,55,55,0.1);} p.test > span{background-color:rgba(55,55,55,0.1);} p.test > span > span{background-color:rgba(55,55,55,0.1);} p.test > span > span > span{background-color:rgba(55,55,55,0.1);} p.test > span > span > span > span{background-color:rgba(55,55,55,0.1);} p.test > span > span > span > span > span{background-color:rgba(55,55,55,0.1);} p.test > span > span > span > span > span > span{background-color:rgba(55,55,55,0.1);} p.test > span > span > span > span > span > span > span{background-color:rgba(55,55,55,0.1);} p.test > span > span > span > span > span > span > span > span{background-color:rgba(55,55,55,0.1);}

One possible solution is using multiple nested tags

I wouldn't suggest using so many spans like the example, however it's just a proof of concept. There are still many bugs that can arise when trying to apply CSS in this manner. (For example altering text-decoration types).


C
CoderPi

I was looking for that like crazy too and I just figured it out by trying different things :P... Well you can do it like that:

composite.something, composite.else
{
    blblalba
}

It suddenly worked for me :)


Doesn't work if some of the classes are in a fixed library file.
h
hydrix

In specific circumstances you can do a "soft" inheritance:

.composite
{
display:inherit;
background:inherit;
}

.something { display:inline }
.else      { background:red }

This only works if you are adding the .composite class to a child element. It is "soft" inheritance because any values not specified in .composite are not inherited obviously. Keep in mind it would still be less characters to simply write "inline" and "red" instead of "inherit".

Here is a list of properties and whether or not they do this automatically: https://www.w3.org/TR/CSS21/propidx.html


N
Nesha Zoric

Less and Sass are CSS pre-processors which extend CSS language in valuable ways. Just one of many improvements they offer is just the option you're looking for. There are some very good answers with Less and I will add Sass solution.

Sass has extend option which allows one class to be fully extended to another one. More about extend you can read in this article


C
Community

Actually what you're asking for exists - however it's done as add-on modules. Check out this question on Better CSS in .NET for examples.

Check out Larsenal's answer on using LESS to get an idea of what these add-ons do.


Z
Zack The Human

CSS doesn't really do what you're asking. If you want to write rules with that composite idea in mind, you may want to check out compass. It's a stylesheet framework which looks similar to the already mentioned Less.

It lets you do mixins and all that good business.


Adding more details to above, Compass aka Sass does via Extend, PlaceHolders Mixins vs Extend , more detailed information about PlaceHolders
S
Shakir

For those who are not satisfied with the mentioned (excellent) posts, you can use your programming skills to make a variable (PHP or whichever) and have it store the multiple class names.

That's the best hack I could come up with.

<style>
.red { color: red; }
.bold { font-weight: bold; }
</style>

<? define('DANGERTEXT','red bold'); ?>

Then apply the global variable to the element you desire rather than the class names themselves

<span class="<?=DANGERTEXT?>"> Le Champion est Ici </span>

B
Benjam

Have a look at CSS compose: https://bambielli.com/til/2017-08-11-css-modules-composes/

according to them:

.serif-font {
    font-family: Georgia, serif;
}

.display {
    composes: serif-font;
    font-size: 30px;
    line-height: 35px;
}

I use it in my react project.


m
miquelvir

I think this one is a better solution:

[class*=“button-“] {
  /* base button properties */
}
.button-primary { ... }
.button-plain { ... }

More on this technique at coderwall.com/p/lqjd1w/css-class-inheritance-in-css. A comment there was critical of performance. Any good blog posts on performance impact? (Good or bad welcome.) My user base is mostly desktop (80%) and some high-end phones (5%) and iPad (5%), so if performance is "OK" on desktop browsers I might stick with this method over adopting LESS/SASS for CSS class inheritance.
B
BloDoe

If you want a more powerful text preprocessor than LESS, check out PPWizard:

http://dennisbareis.com/ppwizard.htm

Warning the website is truly hideous and there's a small learning curve, but it's perfect for building both CSS and HTML code via macros. I've never understood why more web coders don't use it.


The website is truly hideous.
Kind of ironic on a website for an html processor!
Yes, the website is hideous, but it's more than just that. It's hard to read and makes my head hurt, too!
A good thing that it's compatible with windows 3.1 to XP, lol
A bizarre non-standard tool, no like.
j
john

You can achieve what you want if you preprocess your .css files through php. ...

$something='color:red;'
$else='display:inline;';
echo '.something {'. $something .'}';
echo '.else {'. $something .'}';
echo '.somethingelse {'. $something  .$else '}';

...