简体   繁体   中英

Is there a way to have the equivalent of multiple :before and :after pseudo-elements in CSS?

Currently I have this markup that represents an icon container and some elements styled with CSS inside it that in the end show as graphic icon.

    <div class="icon">
        <div class="icon-element1"></div>
        <div class="icon-element2"></div>
        <div class="icon-element3"></div>
    </div>

The number of the child elements can be different depending on the complexity of the icon.

What I want is to somehow move as much as possible to CSS stylesheet, so that ideally I would have only <div class="icon"></div> and the rest would just render from CSS styles, something close in concept to :before/:after , a kind of virtual divs. I don't want to use JavaScript to add the elements dynamically. It would be possible to do this if we had multiple :before/:after .

Here is an example of an icon I get by using the markup from above:

图标

As you can see, there are 3 child elements representing gray case, white screen and turquoise button.

Please advise, how I can simplify this markup so that not to have to put all the divs each time I want this icon to be shown.

You could use nth-child() .

.icon:nth-child(2) {
    color:red;
}

In this instance, the selector would effectively style the second child of .icon .

You wouldn't need the redundant .icon-element classes.

I know you said that the number of child elements will be different, however, there is no difference between this method and the method you are currently using anyways other than reduced markup - which is exactly what you want.

Additionally, there is also the adjacent sibling selector + which could also be effectively used.

You can actually achieve the icon in your image using just ::before and ::after , if you set position:relative on <div class="icon"> , and position the pseudo-elements absolutely:

http://jsfiddle.net/RMs2L/3/

.icon {
    position: relative;
    width: 160px;
    height: 160px;
    background: #666;
}

.icon::before,
.icon::after {
    content: '';
    position: absolute;
    width: 120px;
    left: 20px;
}

.icon::before {
    height: 80px;
    top: 20px;
    background: #fff;
}

.icon::after {
    height: 20px;
    bottom: 20px;
    background: #00b9ae;
}

(Not tested in IE.)

But you're quite right that for icons with more than three parts, just ::before and ::after wouldn't cut it.

If your icons are only made up of areas of flat colour (or gradients), then multiple gradient backgrounds might work for icons with more elements:

http://jsfiddle.net/RMs2L/5/

.icon {
    position: relative;
    width: 160px;
    height: 160px;
    background-color: #666;
    background-image: linear-gradient(to bottom, #fff 0%, #fff 100%)
                    , linear-gradient(to bottom, #00b9ae 0%, #00b9ae 100%)
                    , linear-gradient(to bottom, #000 0%, #000 100%);
    background-size: 120px 40px
                   , 120px 20px
                   , 120px 20px;
    background-position: 20px 20px
                       , 20px 80px
                       , 20px 120px;
    background-repeat: no-repeat;
}

You could even do the same thing with one gradient background, using sharp gradient boundaries:

http://jsfiddle.net/RMs2L/6/

background-image: linear-gradient(to bottom, 
                  #fff 0px, #fff 40px,
                  rgba(0,0,0,0) 40px, rgba(0,0,0,0) 60px,
                  #00b9ae 60px, #00b9ae 80px,
                  rgba(0,0,0,0) 80px, rgba(0,0,0,0) 100px,
                  #000 100px, #000 120px);
background-size: 120px 120px;
background-position: 20px 20px;

And, of course, you can use actual background image files as well as, or instead of, gradients.

As you can see, the CSS is much more fiddly if you try to make icons out of gradient backgrounds, as compared to styling actual elements or pseudo-elements. It might make for clearer code if you suck it up and put in the HTML elements, and style them using :nth-child , as suggested elsewhere.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM