我希望有人可以帮我找到一个优雅的方法来获得CSS箭头边框上的边框.
我想创建这个:
这是我到目前为止的代码:
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,.07),0 2px 0 0 rgba(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,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,.1); }
这是一个工作的JS小提琴https://jsfiddle.net/kdeo3wpg/
正如你所看到的那样,我在主要消息的右侧有一个蓝色边框,但我也想不通办法在箭头上获得蓝色边框.如果可能的话我真的想避免使用图像.找到一个只有CSS的解决方案会很棒.
我曾想过尝试使用:在sudo元素之前,但我无法获得我需要的完全控制权.
任何帮助将不胜感激.
UPDATE
我设法找到了解决方案,但说实话,它不是很干净.
https://jsfiddle.net/kdeo3wpg/1/
我所做的是添加一个新元素,它是边框的宽度并具有相同的背景颜色.然后我将高度设置为略小于CSS箭头的高度.然后我给我的新元素一个CSS箭头边框的背景颜色.
这是新代码:
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,.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,.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,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,.1); }
虽然这个解决方案有效,但我觉得可能有更好更清洁的选择,所以我仍然愿意接受建议.
解决方法
使用svg,您可以创建文本气泡并将linearGradient应用于它.
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,1 -5,-5" fill="url(#grad)" /> <text x="50%" y="40%" text-anchor="middle" font-size="10">Great Thanks</text> </svg>
要使文本气泡具有动态文本,您需要将三角形用作svg.文本将在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:
要向svg添加Box-shadow,您必须在路径上应用svg过滤器.通过CSS执行它将无法工作,因为CSS无法查看实际路径.
feFuncA元素的slope属性控制阴影的不透明度,feOffset是自解释的.
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,.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,-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>
重用svg:
要多次使用相同的svg路径,可以在defs元素中定义path元素,并使用use元素多次使用它,如下例所示.
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,.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>