Using CSS borders to create shapes with pseudo-elements with same height as parent

纵饮孤独 提交于 2020-01-25 08:34:21

问题


I am trying to create "ribbon" headings for my website.

This is what I've been able to mock up so far.

This works properly with short headings (for some value of short), but fails when the headings want to wrap. Is it possible to use the border method of creating the "swallowtail" shape but have the border widths of the :after pseudo-elements be related to the height of the parent instead of hard-coded without resorting to scripting?

Is there an alternative approach to be taken to achieve a similar visual effect?

html, body, div { margin: 0; }
body { background: lightgrey; }
.wrapper {
    background: white;
    padding: 2em;
    padding-top: 0;
    margin: 2em;
    margin: 2em auto;
    width: 80%;
}
.ribbon {
    font-size: 32px;
    line-height: 1.5em;
    display: inline-block;
    font-family: Optima;
    color: white;
    background: #9c0000;
    margin: 0;
    position: relative;
    width: 100%;
    padding: 1em;
    padding-left: 1.5em;
    left: -1.5em;
    filter: drop-shadow(5px 5px 3px grey);
    -webkit-filter: drop-shadow(5px 5px 3px grey);
    -moz-filter: drop-shadow(5px 5px 3px grey);
    margin-top: 1em;
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
}
.ribbon-bot:before {
    position: absolute;
    height: 0;
    width: 0;
    content: "";
    border-color: red green blue yellow;
    border-color: #4d0000 #4d0000 transparent transparent;
    border-style: solid;
    border-width: 0.1em 0.25em 0.1em 0.25em;
    left: 0em;
    bottom: -0.199375em;
}
.ribbon-top:before {
    position: absolute;
    height: 0;
    width: 0;
    content: "";
    border-color: transparent #4d0000 #4d0000 transparent;
    border-style: solid;
    border-width: 0.1em 0.25em 0.1em 0.25em;
    left: 0em;
    top: -0.199375em;
}
.ribbon:after {
    position: absolute;
    width: 0;
    right: -20px;
    bottom: 0px;
    content: "";
    border-color: #9c0000 transparent #9c0000;
    border-width: 1.75em 20px 1.75em 0;
    border-style: solid;
    z-index: -1;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    <div class="wrapper">
        <div class="ribbon ribbon-bot">Ribbon</div>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut non mi libero. Nam 
ultrices malesuada nulla, eu faucibus eros. Nulla non est odio. Maecenas 
vulputate nec sem vitae viverra. In vitae dapibus purus. Morbi mattis mi nulla, 
sed iaculis justo mollis et. Integer porttitor augue nisl, ac auctor nisl 
posuere vitae. Praesent at ligula fermentum, maximus mi ac, vehicula mi. Nam 
ligula mi, suscipit id dictum nec, varius sagittis nisl. Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Suspendisse consequat ipsum a nibh imperdiet 
interdum.</p>

        <div class="ribbon ribbon-top">A Moderately Long Heading Goes Here A Moderately Long Heading Goes Here</div>
        <p>Donec venenatis ante tellus, venenatis consectetur arcu sagittis at. Phasellus 
eu neque a dolor porta rutrum et ac lorem. Nulla ornare nisl quis est lacinia 
vehicula. Sed elementum ante elit, interdum porta elit tristique ac. Praesent 
felis dolor, luctus elementum nisi non, vehicula aliquet mauris. Vestibulum 
fermentum erat nibh, in facilisis lorem bibendum sed. Phasellus condimentum 
pharetra quam, et placerat massa auctor nec. Mauris fringilla hendrerit lectus, 
nec congue elit semper tempus. Pellentesque convallis interdum ligula, et 
faucibus nulla vulputate eget. Donec mattis orci at leo fringilla mollis.</p>
    </div>
</body>
</html>

回答1:


I would create the same shape using gradient and it will be responsive like you want:

html, body, div { margin: 0; }
body { background: lightgrey; }
.wrapper {
    background: white;
    padding: 2em;
    padding-top: 0;
    margin: 2em;
    margin: 2em auto;
    width: 80%;
}
.ribbon-bot,
.ribbon-top{
    font-size: 32px;
    line-height: 1.5em;
    display: inline-block;
    color: white;
    background: 
     /*the small triangl at the bottom left*/
     linear-gradient(to bottom left, #4d0000 49%,transparent 50%) bottom left/15px 12px,
     /*the 2 triangle shape at the left*/
     linear-gradient(to top right,   #9c0000 49%,transparent 50%) 100% calc(100% - 12px)/20px calc(50% - 6px),
     linear-gradient(to bottom right,#9c0000 49%,transparent 50%) right top/20px calc(50% - 6px),
     /*the main part*/
     linear-gradient(#9c0000,#9c0000) left top/calc(100% - 20px) calc(100% - 12px);
    background-repeat:no-repeat;
    position: relative;
    width: 100%;
    padding: 1em;
    padding-left: 1.5em;
    left: -1.5em;
    filter: drop-shadow(5px 5px 3px grey);
    margin-top: 1em;
}
.ribbon-top {
   background: 
     linear-gradient(to top left, #4d0000 49%,transparent 50%) top left/15px 12px,
     linear-gradient(to top right,#9c0000 49%,transparent 50%) bottom right /20px calc(50% - 6px),
     linear-gradient(to bottom right,#9c0000 49%,transparent 50%) 100% 12px/20px calc(50% - 6px),
     linear-gradient(#9c0000,#9c0000) left bottom/calc(100% - 20px) calc(100% - 12px);
     background-repeat:no-repeat;
}
<div class="wrapper">
        <div class="ribbon-bot">Ribbon</div>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut non mi libero. Nam 
ultrices malesuada nulla, eu faucibus eros. Nulla non est odio. Maecenas 
vulputate nec sem vitae viverra. In vitae dapibus purus. Morbi mattis mi nulla, 
sed iaculis justo mollis et. Integer porttitor augue nisl, ac auctor nisl 
posuere vitae. Praesent at ligula fermentum, maximus mi ac, vehicula mi. Nam 
ligula mi, suscipit id dictum nec, varius sagittis nisl. Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Suspendisse consequat ipsum a nibh imperdiet 
interdum.</p>

        <div class="ribbon-top">A Moderately Long Heading Goes Here A Moderately Long Heading Goes Here</div>
        <p>Donec venenatis ante tellus, venenatis consectetur arcu sagittis at. Phasellus 
eu neque a dolor porta rutrum et ac lorem. Nulla ornare nisl quis est lacinia 
vehicula. Sed elementum ante elit, interdum porta elit tristique ac. Praesent 
felis dolor, luctus elementum nisi non, vehicula aliquet mauris. Vestibulum 
fermentum erat nibh, in facilisis lorem bibendum sed. Phasellus condimentum 
pharetra quam, et placerat massa auctor nec. Mauris fringilla hendrerit lectus, 
nec congue elit semper tempus. Pellentesque convallis interdum ligula, et 
faucibus nulla vulputate eget. Donec mattis orci at leo fringilla mollis.</p>
    </div>

Another way is to keep your code and use clip-path with the :after pseudo element:

html, body, div { margin: 0; }
body { background: lightgrey; }
.wrapper {
    background: white;
    padding: 2em;
    padding-top: 0;
    margin: 2em;
    margin: 2em auto;
    width: 80%;
}
.ribbon {
    font-size: 32px;
    line-height: 1.5em;
    display: inline-block;
    font-family: Optima;
    color: white;
    background: #9c0000;
    margin: 0;
    position: relative;
    width: 100%;
    padding: 1em;
    padding-left: 1.5em;
    left: -1.5em;
    filter: drop-shadow(5px 5px 3px grey);
    -webkit-filter: drop-shadow(5px 5px 3px grey);
    -moz-filter: drop-shadow(5px 5px 3px grey);
    margin-top: 1em;
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
}
.ribbon-bot:before {
    position: absolute;
    height: 0;
    width: 0;
    content: "";
    border-color: #4d0000 #4d0000 transparent transparent;
    border-style: solid;
    border-width: 0.1em 0.25em 0.1em 0.25em;
    left: 0em;
    bottom: -0.199375em;
}
.ribbon-top:before {
    position: absolute;
    height: 0;
    width: 0;
    content: "";
    border-color: transparent #4d0000 #4d0000 transparent;
    border-style: solid;
    border-width: 0.1em 0.25em 0.1em 0.25em;
    left: 0em;
    top: -0.199375em;
}
.ribbon:after {
    position: absolute;
    width: 20px;
    left:100%;
    top: 0;
    height:100%;
    content: "";
    background: #9c0000;
    -webkit-clip-path: polygon(0% 0%, 100% 0, 0 50%, 100% 100%, 0% 100%);
    clip-path: polygon(0% 0%, 100% 0, 0 50%, 100% 100%, 0% 100%);
}
<div class="wrapper">
        <div class="ribbon ribbon-bot">Ribbon</div>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut non mi libero. Nam 
ultrices malesuada nulla, eu faucibus eros. Nulla non est odio. Maecenas 
vulputate nec sem vitae viverra. In vitae dapibus purus. Morbi mattis mi nulla, 
sed iaculis justo mollis et. Integer porttitor augue nisl, ac auctor nisl 
posuere vitae. Praesent at ligula fermentum, maximus mi ac, vehicula mi. Nam 
ligula mi, suscipit id dictum nec, varius sagittis nisl. Lorem ipsum dolor sit 
amet, consectetur adipiscing elit. Suspendisse consequat ipsum a nibh imperdiet 
interdum.</p>

        <div class="ribbon ribbon-top">A Moderately Long Heading Goes Here A Moderately Long Heading Goes Here</div>
        <p>Donec venenatis ante tellus, venenatis consectetur arcu sagittis at. Phasellus 
eu neque a dolor porta rutrum et ac lorem. Nulla ornare nisl quis est lacinia 
vehicula. Sed elementum ante elit, interdum porta elit tristique ac. Praesent 
felis dolor, luctus elementum nisi non, vehicula aliquet mauris. Vestibulum 
fermentum erat nibh, in facilisis lorem bibendum sed. Phasellus condimentum 
pharetra quam, et placerat massa auctor nec. Mauris fringilla hendrerit lectus, 
nec congue elit semper tempus. Pellentesque convallis interdum ligula, et 
faucibus nulla vulputate eget. Donec mattis orci at leo fringilla mollis.</p>
    </div>


来源:https://stackoverflow.com/questions/51680642/using-css-borders-to-create-shapes-with-pseudo-elements-with-same-height-as-pare

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!