61

Creating a DIV that uses CSS to draw a triangle to the left. Trying to apply a uniform box-shadow to both parent and the pseudo element (see images) and code.

Is this possible? Or am I better off using border-image for this?

(Top: Before Shadow, Middle: CSS Box-Shadow, Bottom: Desired Result)

Elements Before Box-Shadow is added

Elements with box-shadow added

The desired result

.bubble{
    height: 200px;
    width:  275px;

    opacity: 0;

    margin-top: 41px;

    float: right;

    background-color: #F2F2F2;

    -webkit-border-radius: 5px;
    -webkit-box-shadow: 0px 0px 6px #B2B2B2;
}

.bubble::after {
        height: 0px;
        width:  0px;

        content: "\00a0";

        display: block;

        margin-left: -10px;
        margin-top:   28px;

        border-width: 10px 10px 10px 0;
        border-style: solid;
        border-color: transparent #F2F2F2 transparent transparent;

        -webkit-box-shadow: 0px 0px 6px #B2B2B2;
    }
web-tiki
  • 99,765
  • 32
  • 217
  • 249
Lord Varlin
  • 834
  • 1
  • 8
  • 13

5 Answers5

120

Instead of using a triangle hack, you can just rotate a div using transform and get a real box-shadow. Since you only want the shadow on one side of the div (the visible triangle side), you have to make the blur smaller and lower the opacity.

Demo: http://jsfiddle.net/ThinkingStiff/mek5Z/

HTML:

<div class="bubble"></div>

CSS:

.bubble{
    background-color: #F2F2F2;
    border-radius: 5px;
    box-shadow: 0px 0px 6px #B2B2B2;
    height: 200px;
    margin: 20px;
    width:  275px;
}

.bubble::after {
    background-color: #F2F2F2;
    box-shadow: -2px 2px 2px 0 rgba( 178, 178, 178, .4 );
    content: "\00a0";
    display: block;
    height: 20px;
    left: -10px;
    position: relative;
    top: 20px;
    transform:             rotate( 45deg );
        -moz-transform:    rotate( 45deg );
        -ms-transform:     rotate( 45deg );
        -o-transform:      rotate( 45deg );
        -webkit-transform: rotate( 45deg );
    width:  20px;
}

Output:

enter image description here

ThinkingStiff
  • 64,767
  • 30
  • 146
  • 239
  • 4
    @LordVarlin I recently used it for an iPhone back button so I didn't have to use an image. For even more fun you can use `transform: skew();` to change the angle of the triangle. – ThinkingStiff Jan 15 '12 at 06:02
  • 1
    I checked out the Fiddle with Firefox 14 and it displayed a rectangle instead of a triangle. Why is that? Transformation CSS is supported in FF14, right? – thomthom Aug 14 '12 at 09:59
  • Had to use `skewX` instead of just plain `skew`: `-moz-transform: rotate( 29deg ) skewX( -35deg );` – thomthom Aug 14 '12 at 10:09
  • Nice solution, but how would you put the pointer below the box? – berto77 Dec 01 '12 at 02:51
  • @berto77 Change `left`, `top`, and the first two values of `box-shadow`. – ThinkingStiff Dec 01 '12 at 04:25
  • 1
    I had to add all vendor prefixes for rotate for this to work in all browsers. Add this to the bubble:after CSS: -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -o-transform: rotate(45deg); -ms-transform: rotate(45deg); transform: rotate(45deg); – jetlej Apr 15 '14 at 21:24
  • 2
    @jetlej That's in the demo link. I'll modify the answer. Thanks! – ThinkingStiff Apr 17 '14 at 16:42
  • @jetlej thanks for the cross-browser code. ThinkingStiff, will you please add that code to the answer? It does not work as is, e.g. on iPhone. – Dennis Golomazov Jun 23 '15 at 11:38
  • @DenisGolomazov Done. Thanks. Strange, I thought I'd already made this edit. – ThinkingStiff Jun 23 '15 at 17:12
  • 1
    But using **clip-path** you can also create more [sophisticated shadows](http://jsfiddle.net/mek5Z/2652/). I've modified your fiddle to create an example of this. – Robert Koritnik Dec 01 '15 at 08:43
8

Here is a complete working example in full (S)CSS, with variables for nose size shadow width and an optional border.

The trick is to get the offsets and transform right to achieve pixel-perfection, and to use overflow:hidden as necessary to cut the nose of your bubble (especially if you need borders).

The example in the answer above doesn't work for us because the shadow gets cropped and is laid over the main bubble area.

Degrades gracefully in IE7/8.

HTML:

<div class="chat">
    <div class="bubble">
        <span class='tail'>&nbsp;</span>
        <p>The path of the righteous man is beset on all sides by the iniquities of the selfish and the tyranny of evil men. Blessed is he who, in the name of charity and good will, shepherds the weak through the valley of darkness, for he is truly his brother's keeper and the finder of lost children.</p><p>And I will strike down upon thee with great vengeance and furious anger those who would attempt to poison and destroy My brothers. And you will know My name is the Lord when I lay My vengeance upon thee.</p>
    </div>
</div>

SCSS:

$shadow_radius = 6px;
$nose_size = 12px;
$shadow = 0 1px $shadow_radius #B2B2B2;
$border =  1px solid #bbb

.chat {
    font-family:      sans-serif;
    font-size:        small;
}

.bubble {
    background-color: #F2F2F2;
    border-radius:    5px;
    border:           $border;
    box-shadow:       $shadow;
    display:          inline-block;
    padding:          10px 18px;
    margin-left:     ($shadow_radius + $nose_size);
    margin-right:    ($shadow_radius + $nose_size);
    position:         relative;
    vertical-align:   top;
}

.tail {
    position: absolute;
    top:      $nose_size;
    left:   -($shadow_radius + $nose_size);
    height:  ($shadow_radius + $nose_size);
    width:   ($shadow_radius + $nose_size);
    overflow: hidden;
}
.tail:before {
    border:            $border;
    background-color:  #F2F2F2;
    box-shadow:        $shadow;
    content:           "\00a0";

    display:           block;
    position:          absolute;
    top:               0px;
    left:              $nose_size;
    height:            $nose_size;
    width:             $nose_size;
    -webkit-transform: skew( -45deg );
    -moz-transform:    skew( -45deg );
}
mezis
  • 379
  • 2
  • 8
7

Another solution is to use filter: drop-shadow(0 1px 2px rgba(0,0,0,.5)); It only places the shadow around the objects shape.

Amir Raminfar
  • 33,777
  • 7
  • 93
  • 123
  • Arriving 9 years later feeling this should be the accepted answer. Simple and effective. – Jette Feb 15 '23 at 12:46
4

I know It's a little bit tricky but, seems nice to me. Here is the fiddle http://jsfiddle.net/dzfj6/

HTML

<div class="bubble">
    <div class="triangle"></div>
    <div class="border"></div>
    <div class="content">some content</div>
</div>

CSS

.bubble
{
    height: 200px;
    width:  275px;
    float:right;
    margin-top: 41px;
    margin-left:11px;
    background-color: #f2f2f2;
    -webkit-border-radius: 5px;
    -webkit-box-shadow: 0px 0px 5px #b2b2b2;
    position:relative;
    z-index:1;
}

.triangle
{
   position:absolute;
   top:12px;
   width: 0;
   height: 0;
   border-top: 15px solid transparent;
   border-bottom: 15px solid transparent;
   border-right: 10px solid #f2f2f2;
   margin-left:-9px;
   z-index:3;
}
.border
{        
   position:absolute;
   top:12px;
   width: 0;
   height: 0;
   border-top: 15px solid transparent;
   border-bottom: 15px solid transparent;
   border-right: 10px solid #e0e0e0;
   margin-left:-10px;
   z-index:2;
}

.content{
   padding:10px;
}

Instead of box-shadow, you can simply use border for buble.

tuze
  • 1,978
  • 2
  • 15
  • 19
-4

Don't use box-shadow.

 height: 200px;
    width:  275px;
    float:right;
    margin-top: 41px;
    margin-left:11px;
    background-color: #f2f2f2;
    -webkit-border-radius: 5px;
    -webkit-box-shadow: 0px 0px 5px #b2b2b2;
    position:relative;
    z-index:1;
ЯegDwight
  • 24,821
  • 10
  • 45
  • 52