Border with a Transparent Centred Arrow

Border with a transparent centred arrow

There are two methods to achieve this using CSS3. One is using skewX on pseudo-elements while the other is using rotate on pseudo-elements. Both the methods are also responsive.

Using Skew:

This method is adapted from web-tiki's answer in this thread. It basically uses two pseudo-elements (with roughly 50% width of the container) that are skewed in opposite directions and positioned appropriately to arrive at the arrow shape. The shapes have borders where as the background is set to transparent meaning the pseudo-elements would produce a bottom border + downward arrow effect. The arrow fill would always be transparent (or body color) in this sample.

body {

background: rgb(245, 242, 242);

}

.bordered {

position: relative;

height: 200px;

width: 200px;

margin: 10px;

line-height: 200px;

}

.bordered:after,

.bordered:before {

position: absolute;

content: ' ';

height: 8px;

width: 50%;

bottom: 0px;

}

.bordered:before {

left: 0px;

border-top: 1px solid gray;

border-right: 1px solid gray;

transform-origin: left bottom;

transform: skewX(45deg);

}

.bordered:after {

right: 0px;

border-top: 1px solid gray;

border-left: 1px solid gray;

transform-origin: right bottom;

transform: skewX(-45deg);

}

.bordered img {

width: 150px;

padding: 25px;

vertical-align: middle;

}

/* Just for demo */

.bordered {

transition: all 1s;

text-align: center;

}

.bordered:hover {

height: 250px;

width: 250px;

line-height: 250px;

}
<!-- library included only to avoid browser prefixes -->

<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>

<div class="bordered">

<img src="http://i.imgur.com/0Xqum3A.png" />

</div>

transparent shape with arrow in upper corner

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>

Need only border for arrow not color

I'd use before, after and transform skew. Gives you more flexibility.

.arrow{

position:relative;

display:inline-block;

min-width:100px;

padding-left:1rem;padding-right:1rem;

text-align:center;

line-height:2;

min-height:2rem;

}

.arrow:before,.arrow:after{

content:" ";

z-index:-1;

display:block;

position:absolute;

left:0;

top:-1px;

border:2px solid red;

height:50%;

width:100%;

}

.arrow:before{

border-bottom:0;

transform:skewX(45deg);

}

.arrow:after{

border-top:0;

top:50%;

transform:skewX(-45deg);

}

.left:before{ transform:skewX(-45deg);}

.left:after{transform:skewX(45deg);}

.blue:before,.blue:after{border-color:blue;}

.bgpink:before,.bgpink:after{background-color: pink}
<div class="arrow"></div>

<br/>

<br/>

<br/>

<div class="arrow left"> to the left </div>

<br/>

<br/>

<br/>

<div class="arrow left blue"> and change border color </div>

<br/>

<br/>

<br/>

<div class="arrow left blue bgpink"> and change bg color too </div>

Inside transparent arrow on the top

As stated in the question, your case is a bit different from the example that was provided by web-tiki. In the example that you were referring to, the border with the transparent cut was included as the bottom border for the image whereas you need it as the top border of the plain text area.

The expected output can be achieved with the same skew technique described in that answer. However, it needs to be tweaked a bit to match your case.

  • First thing is, the skewed pseudo-elements (that produce the border) should be added to the container of plain text area and not the top section which holds the image. This part you have already done correctly.
  • Next, you need to position the border such that even with the border the height of your text container will be equal to the other two images placed by its side. For this, you need to position the elements that form the border within the plain text container (top: 0%) instead of above it (bottom: 100% in your code).
  • Then, if the text container has a non-transparent background, you need to clip it such that it is not present behind the elements that is creating the border effect. This can be achieved by adding a padding-top on the text container equal to the height of the border pseudo-elements and then setting background-clip: content-box to it.
  • Finally, you need to move the entire bottom part up by the same number of pixels as the height of the border in order for the top image to be seen through the transparent cut out area. This can be done by adding a negative margin-top to the bottom container.

Putting it altogether your code should be similar to the below snippet to achieve the effect that you need. (Note: Your fiddle has way too much code and so I have created a simpler sample for the demo).

.section {

height: 200px;

width: 500px;

background: url(http://lorempixel.com/500/200/nature/3);

}

.bottom-container {

margin-top: -15px;

height: 100px;

width: 500px;

}

.text,

.middle-image,

.right-image {

float: left;

height: 100%;

width: calc(100% / 3);

}

.middle-image {

background: url(http://lorempixel.com/200/100/nature/2);

}

.right-image {

background: url(http://lorempixel.com/250/100/nature/1);

}

.text {

position: relative;

box-sizing: border-box;

height: 100%;

padding-top: 15px;

text-align: center;

line-height: 85px;

background: #F7F7F7; /* Just for demo */

background-clip: content-box; /* needed only if your background is not transparent */

overflow: hidden;

}

.text:after,

.text:before {

position: absolute;

content: '';

top: 0px;

height: 15px;

background: rgb(215,182,115);

}

.text:before {

left: 0px;

width: 25%;

transform-origin: left bottom;

transform: skew(45deg);

}

.text:after {

right: 0px;

width: 75%;

transform-origin: right bottom;

transform: skew(-45deg);

}
<!-- prefix free library to avoid browser prefixes in CSS -->

<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>

<section class="section">

</section>

<div class="bottom-container">

<div class="text">Some text</div>

<div class="middle-image"></div>

<div class="right-image"></div>

</div>

Border around arrows

you may use gradients and background size to draw parts of arrow and bits of border:

body {

margin: 20px;

font-family: Helvetica;

background: #d4f2ff;

}

#crumbs {

text-align: center;



}

#crumbs ul {

list-style: none;

display: inline-table;

min-width:960px

}

#crumbs ul li {

float:left;;

}

#crumbs ul li a {

float: left;

height: 50px;

background: linear-gradient(to right, transparent 1.2em, #3498db 1.2em);

/* leave some blank bg to draw arrow */

text-align: center;

padding: 30px 40px 0 80px;

position: relative;

margin: 0 10px 0 0;

border-top: 2px solid orange;

border-bottom: 2px solid orange;

font-size: 20px;

text-decoration: none;

color: #fff;

}

li+li {

position: relative;

margin-left: 7px;

}

li+li a:before {

content: '';

position: absolute;

width: 3em;

top: 0px;

bottom: 0px;

left: calc(-1em - 5px);

background: linear-gradient(60deg, #3498db 1.2em, orange 1.25em,orange calc(1.2em + 3px), transparent calc(1.2em + 4px), transparent calc(2.2em - 3px), orange calc(2.2em - 2px), orange 2.2em, #3498db 2.35em)top no-repeat, linear-gradient(120deg, #3498db 1.2em, orange 1.25em,orange calc(1.2em + 3px), transparent calc(1.2em + 4px), transparent calc(2.2em - 3px), orange calc(2.2em - 2px), orange 2.2em, #3498db 2.35em)bottom left no-repeat;

/* 2 gradients drawing end of arrow , borders and begining of next arrow */

background-size: 100% 50%

}

li a {/* smoothen a bit corners */

border-radius:3px;

}

#crumbs ul li:first-child a {

border-top-left-radius: 10px;

border-bottom-left-radius: 10px;

border-left: 2px solid orange;

background: #3498db;/* draww full bg there is no arrows before that one */

}

#crumbs ul li:last-child a {

padding-right: 80px;

border-top-right-radius: 10px;

border-bottom-right-radius: 10px;

border-right: 2px solid orange;

}

/* next is updates of gradients colors and bg for hover state */

#crumbs ul li:hover a:before {

background: linear-gradient(60deg, #3498db 1.2em, orange 1.25em,orange calc(1.2em + 3px), transparent calc(1.2em + 4px), transparent calc(2.2em - 3px), orange calc(2.2em - 2px), orange 2.2em, #fa5ba5 2.35em)top no-repeat, linear-gradient(120deg, #3498db 1.2em, orange 1.25em,orange calc(1.2em + 3px), transparent calc(1.2em + 4px), transparent calc(2.2em - 3px), orange calc(2.2em - 2px), orange 2.2em, #fa5ba5 2.35em)bottom left no-repeat;

background-size: 100% 50%

}

#crumbs ul li:hover +li a:before {

background: linear-gradient(60deg, #fa5ba5 1.2em, orange 1.25em,orange calc(1.2em + 3px), transparent calc(1.2em + 4px), transparent calc(2.2em - 3px), orange calc(2.2em - 2px), orange 2.2em, #3498db 2.35em)top no-repeat, linear-gradient(120deg, #fa5ba5 1.2em, orange 1.25em,orange calc(1.2em + 3px), transparent calc(1.2em + 4px), transparent calc(2.2em - 3px), orange calc(2.2em - 2px), orange 2.2em, #3498db 2.35em)bottom left no-repeat;

background-size: 100% 50%

}

#crumbs ul li:hover a {

background: linear-gradient(to right, transparent 1.2em, #fa5ba5 1.2em);

}

#crumbs ul li:first-child:hover a {

background: #fa5ba5;

}
<div id="crumbs">

<ul>

<li><a href="#1">One</a></li>

<li><a href="#2">Two</a></li>

<li><a href="#3">Three</a></li>

<li><a href="#4">Four</a></li>

<li><a href="#5">Five</a></li>

</ul>

</div>

Background border view with up-arrow triangle | React Native

Add 2 triangle one for background color and one for border color

Sample Image

Complete code

import React, { Component } from "react";
import { View, StyleSheet } from "react-native";

export default class Dashboard extends Component {
render() {
return (
<View style={styles.box}>
<View style={styles.triangle} />
<View style={styles.triangle2} />
</View>
);
}
}

const styles = StyleSheet.create({
box: {
width: 300,
height: 100,
backgroundColor: "#fef6f7",
position: "relative",
margin: 50,
borderColor: "red",
borderWidth: 1
},
triangle: {
width: 10,
height: 10,
position: "absolute",
top: -10,
left: 20,
borderLeftWidth: 10,
borderLeftColor: "transparent",
borderRightWidth: 10,
borderRightColor: "transparent",
borderBottomWidth: 10,
borderBottomColor: "red"
},
triangle2: {
width: 10,
height: 10,
position: "absolute",
top: -10,
left: 21,
borderLeftWidth: 9,
borderLeftColor: "transparent",
borderRightWidth: 9,
borderRightColor: "transparent",
borderBottomWidth: 9,
borderBottomColor: "#fef6f7"
}
});

Link with border and down triangle transparent

The shape given in question is a bit complex to achieve with full transparency because of the area cut by the arrow having to be transparent too. Because of this, the techniques that are generally used for creating such tool-tip like shapes cannot be used as-is here. However, there is a still a way to achieve it using CSS and it is as follows:

  • Use the parent hgroup for the shape with borders on top, left and right and add border-radius. Don't add any border to the bottom because then cutting the space for the arrow would be tough.
  • Use two pseudo elements (:before and :after) which have the same height as the parent but lesser width such that they produce a tiny gap when positioned absolutely with respect to parent. Add border-bottom alone to these pseudo-elements.
  • Add a pseudo-element for the arrow on the arrow-down element (a) and create the arrow using rotate(45deg) transforms instead of using the border trick. The transform method is very helpful for creating transparent arrows. Position this arrow again absolutely with respect to the parent.
  • As we are dealing with transforms, triangle shapes etc the position values need to be calculated based on Math theorems.

* {

box-sizing: border-box;

}

.container {

height: 300px;

width: 500px;

background: url(http://lorempixel.com/500/300/nature/2);

padding: 10px;

}

#subheader {

position: relative;

width: 400px;

height: auto;

border: 1px solid black;

border-bottom: none;

border-radius: 12px;

padding: 10px;

}

.arrow-down{

display: inline-block;

}

.arrow-down:after {

position: absolute;

content: '';

bottom: -10px; /* half the height of the element */

left: 50px; /* some aribitrary position */

height: 20px;

width: 20px;

transform: rotate(45deg);

transform-origin: 50% 50%; /* rotate around center which is at 60px from left */

border-right: 1px solid black;

border-bottom: 1px solid black;

}

#subheader:after {

position: absolute;

content: '';

left: 74px; /* center point of arrow + 1/2 of hypotenuse */

height: 100%;

width: calc(100% - 74px); /* 100% - value of left */

bottom: 0px;

border-bottom: 1px solid black;

border-bottom-right-radius: inherit; /* same border-radius as parent */

}

#subheader:before {

position: absolute;

content: '';

height: 100%;

width: 46px; /* center point of arrow - 1/2 of hypotenuse */

left: 0px;

bottom: 0px;

border-bottom: 1px solid black;

border-bottom-left-radius: inherit; /* same border-radius as parent */

}
<div class='container'>

<hgroup id="subheader">

<h1>lorem ipsum</h1>

<h2>ipsum lorem</h2>

<a href="#" class="arrow-down">Read More</a>

</hgroup>

</div>

CSS: How to attach an arrow to a div and make it overlap the border

CSS solution:

http://jsfiddle.net/wn7JN/

.bubble 
{
position: relative;
width: 400px;
height: 250px;
padding: 0px;
background: #FFFFFF;
border: #000 solid 1px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}

.bubble:after
{
content: "";
position: absolute;
bottom: -25px;
left: 175px;
border-style: solid;
border-width: 25px 25px 0;
border-color: #FFFFFF transparent;
display: block;
width: 0;
z-index: 1;
}

.bubble:before
{
content: "";
position: absolute;
top: 250px;
left: 174px;
border-style: solid;
border-width: 26px 26px 0;
border-color: #000 transparent;
display: block;
width: 0;
z-index: 0;
}


Related Topics



Leave a reply



Submit