Abhi
Abhi

Reputation: 4261

Box shadow for css generated arrow

I'm using the following code for creating up arrow in css:

border-bottom: 10px solid red;
border-left: 10px solid transparent;
border-right: 10px solid transparent

I also want to apply a box-shadow only to the arrow not the rectangular box around it (FIDDLE). Is it possible this way?

NOTE:- I don't want to use any image, it should be with CSS.

Upvotes: 2

Views: 4069

Answers (3)

Woodrow Barlow
Woodrow Barlow

Reputation: 9057

A Single-Property CSS-Only Solution

The box-shadow property may not work with the border-triangle-hack, but there's still a single-property solution: the drop-shadow filter.

.shadow {
  filter: drop-shadow(0 0 2px #000);
  -webkit-filter: drop-shadow(0 0 2px #000);
  /* webkit browsers still need the vendor prefix */
}

From the MDN:

Applies a drop shadow effect to the input image. A drop shadow is effectively a blurred, offset version of the input image's alpha mask drawn in a particular color, composited below the image. The function accepts a parameter of type <shadow> (defined in CSS3 Backgrounds), with the exception that the inset keyword is not allowed. This function is similar to the more established box-shadow property; the difference is that with filters, some browsers provide hardware acceleration for better performance.

The arguments to the drop-shadow filter are formatted identically to the values of the box-shadow property (although it cannot make inset shadows). CSS-Tricks has a great article describing CSS filters.

Browser support is decent, but webkit browsers still (as of the time of writing) need the vendor prefix. Currently, these two lines will cover about 75% of users worldwide.

Below is a slightly more robust solution that is still CSS-only, but should work in IE5.5+, FF31+, and webkit browsers (Chrome, Safari, Opera, etc.) bringing your user coverage very close to 100%.

.triangle {
  border-bottom: 10px solid red;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
}

.shadow {
  /* inline svg-filter-fix for Firefox 31 - 33 */
  filter: url('data:image/svg+xml;utf8,<svg height="0" width="0" xmlns="http://www.w3.org/2000/svg"><filter id="drop-shadow"><feGaussianBlur in="SourceAlpha" stdDeviation="2.2"/><feOffset dx="0" dy="0" result="offsetblur"/><feFlood flood-color="#000"/><feComposite in2="offsetblur" operator="in"/><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge></filter></svg>#drop-shadow');
  /* standard syntax, currently only supported by Firefox 34+ */
  filter: drop-shadow(0px 0px 2px #000);
  /* webkit syntax, currently supports about 66% of browsers */
  -webkit-filter: drop-shadow(0px 0px 2px #000);
  /* syntax for IE5.5 - IE7 */
  filter: progid:DXImageTransform.Microsoft.Shadow(Strength=1, offX=0px, offY=0px, Color='#000000');
  /* syntax for IE8+ */
  -ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=1, offX=0px, offY=0px, Color='#000000')";
}
<span class="triangle shadow"></span>

Upvotes: 6

Stewartside
Stewartside

Reputation: 20905

Sadly, using the border hack doesn't work when using box-shadow.

CSS

Instead, you will want to use css transform to rotate an element and hide the overflow. You will need to use a pseudo-element.

.triangle {
  width: 100px;
  height: 50px;
  position: relative;
  overflow: hidden;
  box-shadow: 0 16px 10px -17px rgba(0, 0, 0, 0.5);
}
.triangle:after {
  content: "";
  position: absolute;
  width: 50px;
  height: 50px;
  background: #999;
  transform: rotate(45deg);
  top: 25px;
  left: 25px;
  box-shadow: -1px -1px 10px -2px rgba(0, 0, 0, 0.5);
}
<div class="triangle"></div>

Canvas

var canvas = document.getElementById('triangle');
var context = canvas.getContext('2d');

context.beginPath();
context.moveTo(25, 10);
context.lineTo(40, 40);
context.lineTo(10, 40);
context.lineTo(25, 10);

context.closePath();
context.shadowColor = "rgba(0, 0, 0, 0.4)";
context.shadowBlur = 7;
context.shadowOffsetX = 2;
context.shadowOffsetY = 5;
context.fillStyle = "rgba(132, 28, 255, 0.8)";
context.fill();
<canvas id="triangle" height="50" width="50">Triangle</canvas>

SVG

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="svg-triangle" width="50" height="50" viewBox="0 0 100 100">
  <filter id="dropshadow" height="130%">
    <feGaussianBlur in="SourceAlpha" stdDeviation="5" />
    <!-- stdDeviation is how much to blur -->
    <feOffset dx="0" dy="0" result="offsetblur" />
    <!-- how much to offset -->
    <feMerge>
      <feMergeNode/>
      <!-- this contains the offset blurred image -->
      <feMergeNode in="SourceGraphic" />
      <!-- this contains the element that the filter is applied to -->
    </feMerge>
  </filter>
  <polygon points="50,10 90,90 10,90" style="filter:url(#dropshadow)" />
</svg>

Upvotes: 4

Arun Kumar
Arun Kumar

Reputation: 1667

Try This Way

    .triangle-with-shadow {
  width: 100px;
  height: 100px;
  position: relative;
  overflow: hidden;
  box-shadow: 0 16px 10px -17px rgba(0, 0, 0, 0.5);
}
.triangle-with-shadow:after {
  content: "";
  position: absolute;
  width: 50px;
  height: 50px;
  background: #999;
  transform: rotate(45deg); /* Prefixes... */
  top: 75px;
  left: 25px;
  box-shadow: -1px -1px 10px -2px rgba(0, 0, 0, 0.5);
}

DEMO

Upvotes: 2

Related Questions