40

How to make a box with arrow in CSS?

Making round corner is easy. but any idea to make the arrow on left side without using image.

Is it possible to make possible with

only one elements <p>....</p>

body {
  background: #ff004e;
  padding: 40px
}
p {
  background: white;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  border-radius: 10px;
  width: 250px;
  height: 150px
}
<p></p>

enter image description here

3

5 Answers 5

53

Like this :

.arrow {
    border: solid 10px transparent;
    border-right-color: #FFF;
}

Demo : http://jsfiddle.net/sparkup/edjdxjf2/

UPDATE :

It can also be achieved without empty elements with the css property :before

element:before {
    content: "";
    position: absolute;
    top: 50%;                         // half way down (vertical center).
    margin-top: -15px;                // adjust position, arrow has a height of 30px. 
    left:-30px;
    border: solid 15px transparent;
    border-right-color: #FFF;
    z-index: 1;
}

Demo : http://jsfiddle.net/sparkup/y89f1te0/

hope it helps

Sign up to request clarification or add additional context in comments.

5 Comments

Great but The arrow'a top is not sharp. and it's very good but it would be much better if we can do without empty elements.
Without adding <div id="pointer"></div> is it possible to do woth before:?
I'm not aware of such a method, sorry.
@holodoc: The question linked to by Floern has the scoop.
Nice! I added pointer-events: none; so that the arrow didn't interfere with clicks to the button beneath.
15

Standard Tool-tip

If you want a simple arrow, then you can add a pseudo element with border-right.

body {
    background:#ff004e;
    padding:40px;
}
p {
    background:white;
    border-radius: 10px;
    width:250px;
    height:150px;
    position: relative;
    display: inline-block;
}
p:before {
    content:"";
    position: absolute;
    height: 0px;
    width: 0px;
    top: 60px;
    left: -29px; /* 1px buffer for zooming problems while rendering*/
    border-width: 15px;
    border-color: transparent white transparent transparent;
    border-style: solid;
}
<p></p>

FIDDLE 1

enter image description here


Flat edge Tool-tip

If you want a flat edge for arrow, try this :

body {
    background: #ff004e;
    padding:40px;
}
p {
    background:white;
    border-radius: 10px;
    width:250px;
    height:150px;
    position: relative;
    display: inline-block;
}
p:before {
    content:"";
    position: absolute;
    height: 45px;
    width: 16px; /* 1px buffer for zooming problems while rendering*/
    top: 50px;
    left: -15px; 
    background: white;
}
p:after {
    content:"";
    position: absolute;
    height: 40px;
    width: 15px;
    border-radius: 0 40px 40px 0;
    top: 75px;
    left: -15px;
    background: #ff004e;
    box-shadow: 0 -45px 0 0 #ff004e;
}
<p></p>

FIDDLE 2

enter image description here

Comments

4

My answer (with no flat edge), added some calculation formula:

.mainBox {
    border: solid 1px #e0e0e0;        
}

.mainBox:before {
    content:"";
    position: absolute;
    /*The right value must be calculated with: (top value of after) - (top value of before) = (right value of before) */
    /*example: (-4px) - (-7px) = 3px*/
    right: 72px; 
    /*The `top` value must be identical to border-width*/
    top: -7px; 
    width: 0;
    height: 0;
    border-style: solid;
    /*The `border-width` value must be identical to top*/
    border-width: 0 7px 7px 7px;
    /*The border color 3rd (#e0e0e0) value must be identical to its parent border color*/
    border-color: transparent transparent #e0e0e0 transparent;
    /*The (z-index of before) must at least one below the (z-index of after)*/
    /*Example: (z-index of before) < (z-index of after) or 9998 < 9999*/
    z-index:9998;
}

.mainBox:after {
    content:"";
    position: absolute;
    right: 75px;
    top: -4px; /*suppose to be identical to border-width*/
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 0 4px 4px 4px;
    border-color: transparent transparent #fff transparent; 
    z-index:9999;
}

The basic rules are:

  1. The before right value must be calculated with: (after's top) - (before's top) = (before's right)

example: (-4px) - (-7px) = 3px

  1. The before and after's top value must be identical to border-width.

  2. The border color 3rd (#e0e0e0 in the example) value must be identical to its parent border color.

  3. The before's z-index must at least one below the after's z-index.

example: (before's z-index) < (after's z-index) or 9998 < 9999.

The result:

enter image description here

Comments

0
a.right{ border-style: dashed;
  border-color: transparent;
  border-width: 0.53em;
  display: -moz-inline-box;
  display: inline-block;
  font-size: 100px;
  height: 0;
  line-height: 0;
  position: relative;
  vertical-align: middle;
  width: 0; border-left-width: 1em;
  border-left-style: solid;
  border-left-color: #666;
  left: 0.25em; }

the above code can be used for right arrow.

Comments

-1

You can make use of span if u don't want to use a div.

span#pointer{border:solid 10px transparent;border-right-color:#fff;position:absolute;margin:-85px 0 0 -20px;}

http://jsfiddle.net/SSKwn/

1 Comment

my point was empty element is not semantically good not to change div to span

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.