4

I'm trying to make a container that has an upward arrow attached to it. I am familiar with the border drawing trick and think that's a likely solution, but it only works for known sizes I think, since you have to specify border in em or px.

The shape I would like to make is this:

          .
         / \
        /   \
       /     \
      | flex  |
      |       |

Where the content area can flex to different sizes as a percentage of a parent container.

Here is the CSS, with the problem area flagged:

.metric {
    display: inline-block;
    position: relative;
    height: 150px;
    width: 50%;
    background: lawngreen;
}

.metric:after {
    position: absolute;
    top: -25px;
    left: 0;
    content: '';
    background: white;
    width: 100%;
    height: 0;
    border: 75px solid white; /* this fixed width is the problem */
    border-top: none;
    border-bottom: 25px solid lawngreen;
    box-sizing: border-box;
}

Here is the jsfiddle: http://jsfiddle.net/C8XJW/2/

Do you guys know any way to pull this off?

Community
  • 1
  • 1
SimplGy
  • 20,079
  • 15
  • 107
  • 144

4 Answers4

6

Here is another posibility.

This one does the trick with gradient backgrounds. You need 2 of them, so that the diagonal is easily achieved:

Relevant CSS:

.metric:before, .metric:after {
    position: absolute;
    top: -25px;
    content: '';
    width: 50%;
    height: 25px;
}
.metric:before {
    left: 0px;
    background: linear-gradient(to right bottom, transparent 50%, lawngreen 50%);
}
.metric:after {
    right: 0px;
    background: linear-gradient(to left bottom, transparent 50%, lawngreen 50%);
}

Updated Fiddle

The differences with Simple As Could Be solution:

Pro Transparent corners (relevant if you have a background)

Con Worse browser support

vals
  • 61,425
  • 11
  • 89
  • 138
  • Wow, that's really nice. I like that one – SimplGy Jul 02 '13 at 21:50
  • Since the overflow:hidden border solution depends on box-sizing:border-box, the compatibility is probably similar between our two solutions and the linear-gradient one degrades better. – SimplGy Jul 03 '13 at 17:45
  • It's the first time I get an accepted answer from a self-answered question .-) – vals Jul 03 '13 at 18:14
2

Here's one great solution. Bascially, you make the arrow always centered, and bigger than you'd ever need it, but lop off the overflow.

Here's the JSFiddle: http://jsfiddle.net/nBAK9/4/

And here's the interesting code:

.metric:after {
  position: absolute;
  top: 0;
  left: 50%;
  margin-left: -250px;            /* max expected width /2 */
  content: '';
  background: white;
  width: 500px;                   /* max expected width    */
  height: 0;
  border: 250px solid white;      /* max expected width /2 */
  border-top: none;
  border-bottom: 50px solid #cf6; /* This size adjusts the slope of the triangle */
  box-sizing: border-box;
}
SimplGy
  • 20,079
  • 15
  • 107
  • 144
1

Not sure you can, I played with it found that since em inherits from parents you can play a bit with it.

body{
    font-size: 3em;
}

div {
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 0 3em 4em 7em;
    border-color: transparent transparent #007bff transparent;
    -webkit-transform:rotate(360deg)
}

Fiddle

Jonathan
  • 8,771
  • 4
  • 41
  • 78
0
.top-arrow:before, .top-arrow:after {
    position: absolute;
    top: -25px;
    content: '';
    width: 50%;
    height: 25px;
}
.top-arrow:before {
    left: 0px;
    background: linear-gradient(to right bottom, transparent 50%, black 50%);
}
.top-arrow:after {
    right: 0px;
    background: linear-gradient(to left bottom, transparent 50%, black 50%);
}


<div class="top-arrow"></div>