Give the CSS border to the border on 1 side

I hope someone can help me with trying to find a beautiful elegant way to get the border on the CSS arrow border.

I am trying to create this:

enter image description here

Here is my code:

HTML

<div class="message-container customer"> <p class="message">Great thanks</p> </div> 

CSS

 .message { width: auto; max-width: 66%; padding: 12px 30px; box-sizing: border-box; background: #ffffff; box-shadow: 0 2px 0 2px rgba(177, 177, 177, .07), 0 2px 0 0 rgba(0, 0, 0, .1); margin: 4px 0 0 0; position: relative; float: right; border-right: 4px solid #0892cb; border-radius: 5px 0 0 5px; } .message:after { top: 100%; right: 0; border: solid transparent; content: " "; height: 0; width: 0; position: absolute; pointer-events: none; border-color: rgba(255, 255, 255, 0); border-bottom-color: #FFFFFF; border-width: 10px; margin-right: -14px; margin-top: -10px; transform: rotate(45deg); box-shadow: 0 2px 0 2px rgba(177, 177, 177, .07), 0 2px 0 0 rgba(0, 0, 0, .1); } 

Here is a working JS script https://jsfiddle.net/kdeo3wpg/

As you can see, I have a blue frame to the right of the main message, but I can’t figure out how to get the blue border on the arrow. If at all possible, I would really like to avoid using an image. It would be great to find a CSS-only solution.

I was thinking of trying to use the sudo :before element, but I cannot get the full control that I need.

Any help would be greatly appreciated.

UPDATE

I managed to find a solution, but honestly, this is not very clean.

https://jsfiddle.net/kdeo3wpg/1/

What I did was add a new element, which is the width of the border and has the same background color. Then I set the height a little less than the height of the CSS arrow. Then I give my new CSS arrow element a background color on the border.

Here is the new code:

HTML

 <div class="message-container customer"> <p class="message"> Great thanks <span class="arrow-border"></span> </p> </div> 

CSS

 .message { width: auto; max-width: 66%; padding: 12px 30px; box-sizing: border-box; background: #ffffff; box-shadow: 0 2px 0 2px rgba(177, 177, 177, .07), 0 2px 0 0 rgba(0, 0, 0, .1); margin: 4px 0 0 0; position: relative; float: right; border-right: 4px solid #0892cb; border-radius: 5px 0 0 5px; } .message:after { top: 100%; right: 0; border: solid transparent; content: " "; height: 0; width: 0; position: absolute; pointer-events: none; border-color: rgba(255, 255, 255, 0); border-bottom-color: #FFFFFF; border-width: 10px; margin-right: -14px; margin-top: -10px; transform: rotate(45deg); box-shadow: 0 2px 0 2px rgba(177, 177, 177, .07), 0 2px 0 0 rgba(0, 0, 0, .1); } .arrow-border { position: absolute; background: #0892cb; width: 4px; height: 9px; bottom: -9px; right: -4px; z-index: 1; } .arrow-border:after { top: 100%; right: 0; border: solid transparent; content: " "; height: 0; width: 0; position: absolute; pointer-events: none; border-color: rgba(255, 255, 255, 0); border-bottom-color: #0892cb; border-width: 3px; margin-right: -3px; margin-top: -3px; transform: rotate(45deg); box-shadow: 0 2px 0 2px rgba(177, 177, 177, .07), 0 2px 0 0 rgba(0, 0, 0, .1); } 

While this solution works, I believe that there may be better and cleaner options, so I'm still open to suggestions.

+8
html css css3 css-shapes
source share
4 answers

Using svg , you can create your text bubble and apply linearGradient to it.

 body { background: #eee; } 
 <svg width="100" height="50" preserveAspectRatio="none" viewBox="-1 -1 102 52"> <defs> <linearGradient id="grad"> <stop offset="97%" stop-color="#fff" /> <stop offset="97%" stop-color="#237ACB" /> </linearGradient> </defs> <path d="M0,5 a5,5 0 0,1 5,-5 h95 v45 l-10,-10 h-85 a5,5 0 0,1 -5,-5" fill="url(#grad)" /> <text x="50%" y="40%" text-anchor="middle" font-size="10">Great Thanks</text> </svg> 

For the text bubble to have dynamic text, you need to use a triangle as svg . The text will be outside svg .

 body { background: #eee; } #container { position: relative; display: table; } #text { position: relative; max-width: 200px; padding: 10px; box-sizing: border-box; background: linear-gradient(to right, #fff calc(100% - 3px), #237ACB calc(100% - 3px)); border-top-left-radius: 5px; border-bottom-left-radius: 5px; } #tri { position: absolute; z-index: 1; top: calc(100% - 1px); right: 0; } 
 <div id="container"> <svg id="tri" width="15" height="15" preserveAspectRatio="none" viewBox="0 0 15 15"> <defs> <linearGradient id="grad"> <stop offset="79%" stop-color="#fff" /> <stop offset="79%" stop-color="#237ACB" /> </linearGradient> </defs> <path d="M0,0 h15 v15 l-15,-15" fill="url(#grad)" /> </svg> <div id="text">Text bubble that will change its width to <code>max-width</code>(200px) and height to contain the dynamic text</div> </div> 

box-shadow application:

To add box-shadow to svg , you need to apply svg filter in the path. Doing this with CSS will not work, as CSS cannot see the actual path.

feFuncA The slope attribute element controls the opacity of the shadow, feOffset is self-evident.

 body { background: #eee; } #container { position: relative; display: table; } #text { width: auto; max-width: 66%; padding: 12px 30px; box-sizing: border-box; background: #ffffff; box-shadow: 0 2px 0 2px rgba(177, 177, 177, .07), 0 2px 0 0 rgba(0, 0, 0, .1); margin: 4px 0 0 0; position: relative; float: right; border-right: 5px solid #0892cb; border-radius: 5px 0 0 5px; } #tri { position: absolute; z-index: 1; top: calc(100% - 1px); right: 0; } 
 <div id="container"> <svg id="tri" width="15" height="18" preserveAspectRatio="none" viewBox="0 0 15 18"> <defs> <linearGradient id="grad"> <stop offset="70%" stop-color="#fff" /> <stop offset="70%" stop-color="#0892cb" /> </linearGradient> <filter id="shadow" height="130%"> <feOffset dx="0" dy="2" in="SourceAlpha" result="offout" /> <feComponentTransfer> <feFuncA type="linear" slope="0.1" /> </feComponentTransfer> <feMerge> <feMergeNode/> <feMergeNode in="SourceGraphic" /> </feMerge> </filter> </defs> <path d="M0,0 h15 v15 l-15,-15" filter="url(#shadow)" fill="url(#grad)" /> </svg> <div id="text">Text bubble that will change its width to <code>max-width</code>(200px) and height to contain the dynamic text</div> </div> 

Reusing svg :

To use the same svg path several times, you can define the path element in the defs element and use it several times with the use element, as shown in the example below.

 body { background: #eee; } .containerIn, .containerOut { position: relative; display: table; margin: 4px 0 15px; } .text { width: auto; max-width: 66%; padding: 12px 30px; box-sizing: border-box; background: #ffffff; box-shadow: 0 2px 0 2px rgba(177, 177, 177, .07), 0 2px 0 0 rgba(0, 0, 0, .1); margin: 4px 0 0 0; position: relative; float: right; border-right: 5px solid #0892cb; border-radius: 5px 0 0 5px; } .containerIn .text { border: 0; border-left: 5px solid #689F38; border-radius: 0 5px 5px 0; float: left; } .tri { position: absolute; z-index: 1; top: calc(100% - 1px); right: 0; } .containerIn .tri { left: 0; } 
 <svg width="15" height="18" preserveAspectRatio="none" viewBox="0 0 15 18"> <defs> <linearGradient id="gradRight"> <stop offset="70%" stop-color="#fff" /> <stop offset="70%" stop-color="#0892cb" /> </linearGradient> <linearGradient id="gradLeft"> <stop offset="31%" stop-color="#689F38" /> <stop offset="31%" stop-color="#fff" /> </linearGradient> <filter id="shadow" height="130%"> <feOffset dx="0" dy="2" in="SourceAlpha" result="offout" /> <feComponentTransfer> <feFuncA type="linear" slope="0.1" /> </feComponentTransfer> <feMerge> <feMergeNode/> <feMergeNode in="SourceGraphic" /> </feMerge> </filter> <path id="triRight" d="M0,0 h15 v15z" filter="url(#shadow)" fill="url(#gradRight)" /> <path id="triLeft" d="M0,0 v15 l15,-15z" filter="url(#shadow)" fill="url(#gradLeft)" /> </defs> </svg> <div class="containerOut"> <svg class="tri" width="15" height="18" preserveAspectRatio="none" viewBox="0 0 15 18"> <use xlink:href="#triRight" x="0" y="0" /> </svg> <div class="text">Text bubble that will change its width to <code>max-width</code>(200px) and height to contain the dynamic text</div> </div> <div class="containerIn"> <svg class="tri" width="15" height="18" preserveAspectRatio="none" viewBox="0 0 15 18"> <use xlink:href="#triLeft" x="0" y="0" /> </svg> <div class="text">Text bubble that will change its width to <code>max-width</code>(200px) and height to contain the dynamic text</div> </div> <div class="containerIn"> <svg class="tri" width="15" height="18" preserveAspectRatio="none" viewBox="0 0 15 18"> <use xlink:href="#triLeft" x="0" y="0" /> </svg> <div class="text">Text bubble that will change its width to <code>max-width</code>(200px) and height to contain the dynamic text</div> </div> <div class="containerOut"> <svg class="tri" width="15" height="18" preserveAspectRatio="none" viewBox="0 0 15 18"> <use xlink:href="#triRight" x="0" y="0" /> </svg> <div class="text">Text bubble that will change its width to <code>max-width</code>(200px) and height to contain the dynamic text</div> </div> 
+5
source share

You can use the span for the blue border instead of the border on the p element if you want the border to be larger than the element. You also need to adjust the position.

This will only work on a white background.

 * { box-sizing: border-box; } body { background: white; } .message { width: auto; max-width: 66%; padding: 12px 30px; box-sizing: border-box; background: #ffffff; box-shadow: 0 2px 0 2px rgba(177, 177, 177, .07), 0 2px 0 0 rgba(0, 0, 0, .1); margin: 4px 0 0 0; position: relative; float: right; border-radius: 5px 0 0 5px; margin: 10px; } .message:after { bottom: -9px; right: -5px; border: solid transparent; content: " "; height: 0; width: 0; position: absolute; pointer-events: none; border-color: rgba(255, 255, 255, 0); border-bottom-color: #FFFFFF; border-width: 10px; transform: rotate(45deg); box-shadow: 0 2px 0 2px rgba(177, 177, 177, .07), 0 2px 0 0 rgba(0, 0, 0, .1); } span { content: ''; right: 0; top: 0; position: absolute; height: calc(100% + 18px); border-right: 5px solid #0892cb; display: inline-block; } span:after { content: ''; width: 11px; height: 11px; background: white; position: absolute; bottom: -7px; right: -3px; transform: rotate(50deg); } 
 <div class="message-container customer"> <p class="message">Great thanks <span></span> </p> </div> 

You can also use SVG

 body { background: #F4F4F3; } .st0 { fill: #B2B3B3; } .st1 { font-size: 30px; } .st2 { fill: #FFFFFF; } .st3 { fill: none; } .st4 { fill: #3079BE; } .st5 { font-size: 20; } 
 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="260.5px" height="120.5px" viewBox="0 0 260.5 120.5" style="enable-background:new 0 0 260.5 120.5;" xml:space="preserve"> <path class="st0" d="M256.016,20.217l0.961,97.533l-22.195-22L24.75,96.167c-6.653,0-11.417-5.834-11.917-10.972V20.217 c0-6.429,5.389-11.637,12.042-11.637h219.099c3.51,0,12.041,0,12.041,0S256.016,17.182,256.016,20.217z" /> <g> <path class="st2" d="M256.018,15.976v99.42l-21.16-20.42H25.688c-6.63,0-12-5.38-12-12v-67c0-6.63,5.37-12,12-12h218.33 c3.499,0,12,0,12,0S256.018,12.845,256.018,15.976z" /> <polygon class="st4" points="256.5,116.524 249.813,110.064 249.813,4.493 256.643,4.493 " /> </g> <rect x="84.5" y="36" class="st3" width="109.5" height="19.75" /> <text x="50%" y="60px" text-anchor="middle" class="st1 st5">Great thanks</text> <path class="st0" d="M234.448,97.333" /> </svg> 
+2
source share

If you want to create this project using one element, you can use pseudo-elements to use similar Skews to create a lower triangle, as well as the borders on the right of these elements to create a blue section.

Below is a brief demo:

 .message{ display:inline-block; min-width:100px; position:relative; padding:10px; padding-right:30px; background:lightgray; border-radius:10px 0 0 10px; box-shadow: 0 2px 2px #222; } .message:before,.message:after{ content:""; position:absolute; top:0;right:0; height:100%; width:20px; background:inherit; border-right:5px solid cornflowerblue; } .message:before{ height:50%;top:50%; width:10px; box-shadow:inherit; transform:skewY(45deg); transform-origin:top left; } 
 <div class="message">I'm Doing Well Thanks</div> 
+1
source share

already answered, but with a single element and a pseudo + gradient it was possible to do a quiet similar.

 body { background: #F4F4F3; } span { display: inline-block; position: relative; padding: 1em; margin: 0 1em; border-radius: 5px 0 0 5px; box-shadow: -2px 2px 3px -2px gray; background: #FFFFFF; font-size: 18px; } span:after { content: ''; position: absolute; top:0; /* from here it is a matter of tunning */ bottom:-10px; width:4.5em;/* see this to increase/decrease angle */ background:linear-gradient(230deg, #237ACB 50%,transparent 50% ) no-repeat top right,/* degrees to follow width/angle set earlier */ linear-gradient(to bottom left, #FFFFFF 50%, gray calc(50% + 1px) , transparent calc(50% + 2px) );/* about blending bg and drawing the the slant bottom shadow */ background-size:5px 197%, auto auto;/* about to draw the blue line just as big as it needs */ z-index:-1; right:-11px;/* tune about width /angle given earlier */ } 
 <span> Great thanks</span> 

http://codepen.io/gc-nomade/pen/qNyAVa

0
source share

All Articles