Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

transparent shape with arrow in upper corner

Please see the image below.

Desired result

I want to add an arrow to the top right of a div which I am treating as editable input box. Please help me how I can achieve this using CSS. I cannot use a SVG since I need this as a div to show emoticons as images over it.

<div placeholder="Your message" id="Message">
...
</div>
like image 532
firebolt_ash Avatar asked May 03 '15 07:05

firebolt_ash


People also ask

How do you make an arrow shape in CSS?

Arrows. To create a simple arrow without a tail, make a box with a width and height, border, as well as zero left and top borders. To make an up arrow, add the transform: rotate(225deg); property, and to make a down arrow, add the transform: rotate(45deg); property to rotate the arrow to 225 and 45 degrees respectively ...


2 Answers

You can do it like in the below snippet. The method used to achieve the shape is as given below:

  • The main div element only has a top, bottom and left border. The right border is nullified because the element and its arrows needs to be transparent. With a transparent arrow, if a right border is present that would also get displayed.
  • The arrow on the right is achieved using a skewed element placed with respect to the right edge of the shape.
  • The right border of the shape is achieved by using another pseudo-element whose size is the same as the height of the whole container - height of the arrow pseudo-element. This element is positioned with respect to the bottom right of the shape.

You can adjust the height and border-radius as required. I have set the positioning such that even a change in height/width of parent would not affect it.

div.shape {
  position: relative;
  width: 300px;
  height: 100px;
  padding: 4px;
  margin-top: 20px;
  border: 2px solid gray;
  border-right: none; /* not required as the shape needs to be transparent */
  border-radius: 8px; /* not required as the right border is done through pseudo element */
  border-top-right-radius: 0px;
  border-bottom-right-radius: 0px;
}
div.shape:before {
  position: absolute;
  content: '';
  top: -2px; /* equal to border top of parent - no need to change*/
  right: -6px; /* for positioning - no need to change*/
  height: 15%; /* should be changed depending on height of arrow */
  width: 10%; /* should be changed depending on width of arrow */
  border-top: 2px solid gray;
  border-right: 3px solid gray; /* thicker border because skew makes it thin */

  /* to achieve the arrow like shape */ 
  -webkit-transform-origin: bottom right;
  -webkit-transform: skew(-45deg);
  -moz-transform: skew(-45deg);
  transform: skew(-45deg);
}
div.shape:after {
  position: absolute;
  content: '';
  right: -6px; /* for positioning - no need to change*/
  height: 85%; /* height of parent - height of arrow */
  width: 2%; /* no need to change */
  bottom: -2px; /* equal to border bottom of parent - no need to change*/
  border-right: 2px solid gray;
  border-bottom: 2px solid gray;
  border-bottom-right-radius: 8px; /* for producing curve on bottom right */
}

/* Just for demo */

body {
  background: -webkit-linear-gradient(0deg, crimson, indianred, purple);
  background: -moz-linear-gradient(90deg, crimson, indianred, purple);
  background: linear-gradient(90deg, crimson, indianred, purple);
}
<div class="shape">
  Lorem Ipsum Dolor Sit Amet...
</div>

The arrow can be added to the left side by changing the positioning attributes and the skew direction (from positive angle to negative angle) like in the below snippet.

div.shape {
  position: relative;
  width: 300px;
  height: 100px;
  padding: 4px;
  margin-top: 20px;
  margin-left: 20px;
  border: 2px solid gray;
  border-left: none; /* not required as the shape needs to be transparent */
  border-radius: 8px; /* not required as the right border is done through pseudo element */
  border-top-left-radius: 0px;
  border-bottom-left-radius: 0px;
}
div.shape:before {
  position: absolute;
  content: '';
  top: -2px; /* equal to border top of parent - no need to change*/
  left: -6px; /* for positioning - no need to change*/
  height: 15%; /* should be changed depending on height of arrow */
  width: 10%; /* should be changed depending on width of arrow */
  border-top: 2px solid gray;
  border-left: 3px solid gray; /* thicker border because skew makes it thin */

  /* to achieve the arrow like shape */ 
  -webkit-transform-origin: bottom right;
  -webkit-transform: skew(45deg);
  -moz-transform: skew(45deg);
  transform: skew(45deg);
}
div.shape:after {
  position: absolute;
  content: '';
  left: -6px; /* for positioning - no need to change*/
  height: 85%; /* height of parent - height of arrow */
  width: 2%; /* no need to change */
  bottom: -2px; /* equal to border bottom of parent - no need to change*/
  border-left: 2px solid gray;
  border-bottom: 2px solid gray;
  border-bottom-left-radius: 8px; /* for producing curve on bottom right */
}

/* Just for demo */

body {
  background: -webkit-linear-gradient(0deg, crimson, indianred, purple);
  background: -moz-linear-gradient(90deg, crimson, indianred, purple);
  background: linear-gradient(90deg, crimson, indianred, purple);
}
<div class="shape">
  Lorem Ipsum Dolor Sit Amet...
</div>
like image 160
Harry Avatar answered Nov 16 '22 02:11

Harry


Filter: drop-shadow()

The compatibility is limited

Yet the effect is pretty cool :P

.inputcontainer {
  display: inline-block;
  position: relative;
  filter: drop-shadow(0px 0px 5px black);
  -webkit-filter: drop-shadow(0px 0px 1px black);
}
.input {
  display: inline-block;
  border: none;
  border-radius: 10px;
  border-top-right-radius: 0px;
  width: 280px;
  height: 50px;
  background-color: white;
  padding-left: 20px;
  font-size: 20px;
}
.input:focus {
  outline: none;
}
.arrow {
  position: absolute;
  display: inline-block;
  top: 0;
  right: -5px;
  width: 20px;
  height: 20px;
  background-color: white;
  transform: skew(-45deg);
  z-index: -1;
}
<div class="inputcontainer">
  <input type="text" class="input" placeholder="Your message"/>
  <div class="arrow"></div>
</div>

Box-shadow:

Here the compatibility is a lot better

.inputcontainer {
  display: inline-block;
  position: relative;
  filter: drop-shadow(0px 0px 5px black);
}
.input {
  display: inline-block;
  border: none;
  border-radius: 10px;
  border-top-right-radius: 0px;
  width: 280px;
  height: 50px;
  background-color: white;
  padding-left: 20px;
  font-size: 20px;
  box-shadow: 0px 0px 0px 2px gray;
}
.input:focus {
  outline: none;
}
.arrow {
  position: absolute;
  display: inline-block;
  top: 0;
  right: -8px;
  width: 20px;
  height: 20px;
  background-color: white;
  transform: skew(-45deg);
  box-shadow: 2px -2px 0px 0px gray;
}
<div class="inputcontainer">
  <input type="text" class="input" placeholder="Your message"/>
  <div class="arrow"></div>
</div>
like image 22
Persijn Avatar answered Nov 16 '22 03:11

Persijn