<blockquote class="speech-bubble">
<p>When will Apple release a MacBook Air 15" with Retina?</p>
<cite>John Doe - Developer</cite>
</blockquote>
// This solution uses transforms and a caret mixin.
// What will yours be? Fork this pen and share
// your solution in this comments.
// This pen's solution is on line 91.
/// DEMO
/// ==========================================================
$bg:darken(#8CA8D8, 10%);
html,body{height:100%;}body{display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;background:$bg;}
/// REQUIRED
/// ==========================================================
$gutter: 20px;
$caret-unit: 25px;
$bubble-bg: #8CA8D8;
$bubble-color: white;
$cite-color: $bubble-color;
/// Opposite Direction
/// ==========================================================
/// Returns the opposite direction of each direction in a list
/// @author Hugo Giraudel
/// @param {List} $directions - List of initial directions
/// @return {List} - List of opposite directions
@function opposite-direction($directions) {
$opposite-directions: ();
$direction-map: (
'top': 'bottom',
'right': 'left',
'bottom': 'top',
'left': 'right',
'center': 'center',
'ltr': 'rtl',
'rtl': 'ltr'
);
@each $direction in $directions {
$direction: to-lower-case($direction);
@if map-has-key($direction-map, $direction) {
$opposite-directions: append($opposite-directions, unquote(map-get($direction-map, $direction)));
} @else {
@warn "No opposite direction can be found for `#{$direction}`. Direction omitted.";
}
}
@return $opposite-directions;
}
/// Unit Removal
@function strip-unit($num) {
@return $num / ($num * 0 + 1);
}
/// Triangle Mixin
/// ==========================================================
@mixin caret($point, $border-width, $color) {
$opposite: opposite-direction($point);
border: $border-width solid transparent;
border-#{$opposite}: $border-width solid $color;
border-#{$point}: 0;
height: 0;
width: 0;
}
/// Component
/// ==========================================================
.speech-bubble {
filter: drop-shadow(-1px -1px 2px rgba(black, .10)) drop-shadow(1px 2px 2px rgba(black, .15));
margin: 1rem;
margin-bottom: ($gutter * 2);
padding: 1.5rem 2rem;
position: relative;
font-family: 'Source Sans Pro', sans-serif;
font-size: 1.2rem;
font-weight: 400;
background: $bubble-bg;
color: $bubble-color;
&::before {
@include caret(bottom, ($caret-unit / 2), $bubble-bg);
border-top-width: $caret-unit;
content: '';
display: block;
position: absolute;
left: 3rem;
bottom: -$caret-unit;
transform-origin: center;
transform: rotate(90deg) skew(-(strip-unit($caret-unit))+deg) translateY($caret-unit / 1.5);
}
}
.speech-bubble cite {
position: absolute;
bottom: -2rem;
left: 4.5rem;
font-size: 1rem;
font-style: normal;
font-weight: 300;
letter-spacing: 0.5px;
color: $cite-color;
}
View Compiled
This Pen doesn't use any external CSS resources.