Triangle within a triangle CSS - html

I'm looking to create the following setup for a navigation structure.
I'm able to get the white down triangle working without an issue but how do I place yet another triangle (green lines) over the top of the first one without a full border/background or using an image? I can only get a solid green arrow over the white one and that's not what I want to do.
This is what I currently have.
.custom-nav li a:after {
content: "";
z-index: 99;
width: 0;
height: 0;
border-style: solid;
border-width: 40px 150px 0 150px;
border-color: #ffffff transparent transparent transparent;
position: absolute;
top: 173%; left: -75px;
}
<div>
<ul class="custom-nav">
<li>Environment</li>
<li>Health</li>
</ul>
</div>

I think the best option to get something like that is to use an SVG:
body {
margin: 0;
background: #DEE;
}
.nav {
display: flex;
}
.button {
position: relative;
background: transparent;
border: 0;
width: 50%;
height: 100px;
padding: 0 0 50px;
background: content-box white;
font-family: monospace;
font-weight: bold;
outline: none;
cursor: pointer;
}
.button__text {
position: relative;
z-index: 1;
}
.button__triangle {
position: absolute;
top: 25px;
bottom: 0;
left: 50%;
width: 100%;
transition: transform ease-in 150ms;
transform: translate(-50%, -50%);
}
.button:hover > .button__triangle {
transform: translate(-50%, 0);
}
.button__triangle--big {
fill: white;
}
.button__triangle--small {
fill: white;
stroke: red;
stroke-width: 2px;
stroke-linecap: round;
opacity: 0;
transition: opacity ease-in 150ms;
}
.button:hover .button__triangle--small {
opacity: 1;
}
<nav class="nav">
<button class="button">
<span class="button__text">OPTION 1</span>
<svg viewBox="0 0 200 50" class="button__triangle">
<polygon points="0,0 100,50 200,0" class="button__triangle--big" />
<polyline points="50,5 100,30 150,5" class="button__triangle--small" />
</svg>
</button>
<button class="button">
<span class="button__text">OPTION 2</span>
<svg viewBox="0 0 200 50" class="button__triangle">
<polygon points="0,0 100,50 200,0" class="button__triangle--big" />
<polyline points="50,5 100,30 150,5" class="button__triangle--small" />
</svg>
</button>
</nav>

Multiple background can do this:
.box {
--w:160px; /* width of the arrow */
--h:40px; /* height of the arrow*/
--b:2px; /* thickness of the green arrow */
--o:20%; /* offset of the green arrow */
/* gadient coloration, white then the green border then white again then transparent */
--g:#fff var(--o),
green var(--o) calc(var(--o) + var(--b)),
#fff calc(var(--o) + var(--b) + 1px) 49.8%,
transparent 50%;
height:50px;
margin:5px;
border-bottom:var(--h) solid transparent; /* the arrow will take the border space */
background:
linear-gradient(to bottom right,var(--g)) calc(50% + calc(var(--w)/4)) 100% border-box,
linear-gradient(to bottom left ,var(--g)) calc(50% - calc(var(--w)/4)) 100% border-box,
#fff padding-box;
background-size:calc(var(--w)/2) var(--h);
background-repeat:no-repeat;
}
body {
background:#000;
}
<div class="box"></div>
<div class="box" style="--w:200px;--h:60px;--o:30%;--b:5px"></div>
<div class="box" style="--w:180px;--h:30px;--o:10%;--b:3px"></div>

Related

How to make rounded corners Hexagon with CSS? [duplicate]

This is my CSS.
CSS
#hexagon-circle {
width: 100px;
height: 55px;
background: red;
position: relative;
border-radius: 10px;}
#hexagon-circle:before {
content: "";
position: absolute;
top: -25px;
left: 0;
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 29px solid red;
border-radius: 10px;}
#hexagon-circle:after {
content: "";
position: absolute;
bottom: -25px;
left: 0;
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-top: 29px solid red;
border-radius: 10px;}
The output is 4 edges of hexagon is curved, but top and the bottom is not. I want to make all edge of hexagon curved. How to make top and bottom edge to be curved? or How to make the top edge of triangle to be curved?
http://jsfiddle.net/yR7zt/1
I think you are looking for this.
.hex {
position: relative;
margin: 1em auto;
width: 10em;
height: 17.32em;
border-radius: 1em/.5em;
background: orange;
transition: opacity .5s;
}
.hex:before,
.hex:after {
position: absolute;
width: inherit;
height: inherit;
border-radius: inherit;
background: inherit;
content: '';
}
.hex:before {
-webkit-transform: rotate(60deg);
transform: rotate(60deg);
}
.hex:after {
-webkit-transform: rotate(-60deg);
transform: rotate(-60deg);
}
<div class="hex"></div>
I understand this is a fairly old question, but I thought I'd add an answer to show more about how it works.
So, first off, we need to create a single element on the page. I have gone for a size of height:300px; width:180px; and a border radius of 10px. Just because I like the roundness of the number (forgive the pun). Giving this element a position:relative; means that we can herein position everything absolutely in relative terms to this div.
We then need to create two pseudo elements, with the same height and width as the parent.
Because the pseudo elements are exactly that, pseudo elements, we need to add a content: to them. And since because we can put stuff within the parent, we don't really need these, so set them to "";
this leads us onto how to create the hexagon, rather than the rectangle we currently have. To do that, we're going to have to include a rotation in order to generate the other sides of the hexagon. With there being 6 sides, and the angles needing to add to 360, we can rotate one of the pseudo element by 60 degrees. The other we'll rotate by -60 degrees (or 300degrees, if you'd prefer).
This leaves us with our 'hexagon' in which we can add some nice styling and hover animations as need be:
.roundHex {
position: relative;
margin: 0 auto;
background: rgba(0, 0, 0, 0.2);
border-radius: 10px;
height: 300px;
width: 180px;
transition: all 1s;
line-height:300px;
text-align:center;
color:white;
font-size:20px;
}
.roundHex:before,
.roundHex:after {
content: "";
position: absolute;
top: 0;
left: 0;
background: inherit;
border-radius: inherit;
height: 100%;
width: 100%;
z-index:-1;
}
.roundHex:before {
-webkit-transform: rotate(60deg);
-moz-transform: rotate(60deg);
transform: rotate(60deg);
transition: all 1s 0.5s;
}
.roundHex:after {
-webkit-transform: rotate(-60deg);
-moz-transform: rotate(-60deg);
transform: rotate(-60deg);
transition: all 1s 1s;
}
.roundHex:hover {
background: tomato;
}
<div class="roundHex">HOVER ME</div>
Jsfiddle demo also available
I will consider the same trick I used in the previous answer Where I will build the hexagon using clip-path
.hex {
width: 200px;
display: inline-block;
color:orange;
}
.hex::before {
content: "";
display: block;
background:currentColor;
padding-top: 90%;
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}
<div class="hex"></div>
Then I will apply an SVG filter:
.hex {
width: 200px;
display: inline-block;
color:orange;
filter: url('#goo');
}
.hex::before {
content: "";
display: block;
background:currentColor;
padding-top: 86.6%; /* 100%*cos(30) */
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}
<div class="hex"></div>
<div class="hex" style="color:blue;width:150px;"></div>
<div class="hex" style="color:red;width:100px;"></div>
<svg style="visibility: hidden; position: absolute;" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="goo"><feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9" result="goo" />
<feComposite in="SourceGraphic" in2="goo" operator="atop"/>
</filter>
</defs>
</svg>
And in the opposite direction
.hex {
width: 200px;
display: inline-block;
margin:0 5px;
color:orange;
filter: url('#goo');
}
.hex::before {
content: "";
display: block;
background:currentColor;
padding-top: 115%; /* 100%/cos(30) */
clip-path: polygon(0% 25%,0% 75%,50% 100%,100% 75%,100% 25%,50% 0%);
}
<div class="hex"></div>
<div class="hex" style="color:blue;width:150px;"></div>
<div class="hex" style="color:red;width:100px;"></div>
<svg style="visibility: hidden; position: absolute;" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="goo"><feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9" result="goo" />
<feComposite in="SourceGraphic" in2="goo" operator="atop"/>
</filter>
</defs>
</svg>
Try this way :(works in chrome and in ie 10)
<br><br><br>
<div id="hexagon-circle"></div>
<style>
#hexagon-circle {
position: relative;
margin: 1em auto;
width: 10em; height: 17.32em;
border-radius: 1em/.5em;
opacity: .25;
background: orange;
transition: opacity .5s;
cursor: pointer;
}
#hexagon-circle:before, #hexagon-circle:after {
position: absolute;
width: inherit; height: inherit;
border-radius: inherit;
background: inherit;
content: '';
}
#hexagon-circle:before {
transform: rotate(60deg);
-ms-transform:rotate(60deg); /* IE 9 */
-webkit-transform:rotate(60deg); /* Opera, Chrome, and Safari */
}
#hexagon-circle:after {
transform: rotate(-60deg);
-ms-transform:rotate(-60deg); /* IE 9 */
-webkit-transform:rotate(-60deg); /* Opera, Chrome, and Safari */
}
</style>
You can try this approach:
CSS
#hexagon-circle {
position: relative;
margin: 1em auto;
width: 10em;
height: 17.32em;
border-radius: 1em/.5em;
background: red;
transition: opacity .5s;
cursor: pointer;}
#hexagon-circle:before {
position: absolute;
width: inherit;
height: inherit;
border-radius: inherit;
background: inherit;
content: '';
-webkit-transform: rotate(60deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(60deg); /* IE 9 */
transform: rotate(60deg);} /* Firefox 16+, IE 10+, Opera */
#hexagon-circle:after {
position: absolute;
width: inherit;
height: inherit;
border-radius: inherit;
background: inherit;
content: '';
-webkit-transform: rotate(-60deg); /* Chrome, Opera 15+, Safari 3.1+ */
-ms-transform: rotate(-60deg); /* IE 9 */
transform: rotate(-60deg);} /* Firefox 16+, IE 10+, Opera */
DEMO
http://jsfiddle.net/yR7zt/4/
With your current code, using the triangle top and bottom, you can modify them slightly to give it a curved look. Add a width of 4px to #hexagon-circle:before and #hexagon-circle:after and reduce border-left and border-right by 2px each.
Js Fiddle here
#hexagon-circle {
width: 100px;
height: 55px;
background: red;
position: relative;
border-radius: 10px;
}
#hexagon-circle:before {
content: "";
position: absolute;
top: -25px;
left: 0;
width: 4px;
height: 0;
border-left: 48px solid transparent;
border-right: 48px solid transparent;
border-bottom: 29px solid red;
border-radius: 10px;
}
#hexagon-circle:after {
content: "";
position: absolute;
bottom: -25px;
left: 0;
width: 4px;
height: 0;
border-left: 48px solid transparent;
border-right: 48px solid transparent;
border-top: 29px solid red;
border-radius: 10px;
}
It's not a true curve as it creates a straight line, however it gives the impression it might be curved when viewed in the context of the shape.

How can I add a shadow to this triangle

I have tried adding a shadow to my triangle but it just wont work, this is so annoying!
Heres my code:
function section_about() {
$(".about").css("display", "inline-block");
$(".about").animate({opacity:"1"}, {duration: 1000, queue: false});
window.location.hash = "/About Us/";
}
function triangle_sizer() {
$(".triangle-up").css("border-left-width", jQuery(window).width()/2);
$(".triangle-up").css("border-right-width", jQuery(window).width()/2);
$(".triangle-up").css("top", jQuery(window).height()-125);
$(".triangle-down").css("border-left-width", jQuery(window).width()/2);
$(".triangle-down").css("border-right-width", jQuery(window).width()/2);
$(".triangle-down").css("top", jQuery(window).height()-125);
}
triangle_sizer();
jQuery(window).resize(function() {
triangle_sizer();
});
##style.css##
.triangle-down {
width: 0;
height: 0;
border-style: solid;
border-width: 100px 200px 0 100px;
border-color: rgba(39, 39, 39, 1) transparent transparent transparent;
box-shadow: 0 16px 10px -17px rgba(0, 0, 0, 0.5);
}
.triangle-down:after {
content: "";
position: absolute;
width: 0;
height: 0;
background: rgba(39, 39, 39, 1);
-webkit-transform: rotate(45deg);
box-shadow: -1px -1px 10px -2px rgba(0, 0, 0, 0.5);
}
.par {
position: absolute;
top: 200%;
width: 100%;
height: 0%;
}
/* Arrows */
.arrows {
width: 220px;
height: 144px;
position: absolute;
left: 50%;
top: 70%;
margin-left: -76.5px;
}
.arrows path {
stroke: white;
fill: transparent;
stroke-width: 1px;
}
/* Arrows */
.arrows-down {
width: 220px;
height: 144px;
position: absolute;
left: 50%;
top: 70%;
margin-left: -78.5px;
}
.arrows-down path {
stroke: white;
fill: transparent;
stroke-width: 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="par">
<div class="triangle-down">
<svg class="arrows-down" viewbox="0 0 102 102">
<path class="a1" d="M0 20 L30 52 L60 20"></path>
</svg>
</div>
</div>
I have been searching for a solution for a long time and cant find one. This is what happens when that code is ran:
https://gyazo.com/c890a79c547f5624c97abacc66104fc1
https://jsfiddle.net/Lec8862y/2/
HTML
<span class="triangle">▼</span>
CSS
span {
display: inline-block;
transform: scaleX(8.5);
color: lightgreen;
text-shadow:
0 2px 2px rgba(255,255,255,0.7),
0 10px 4px rgba(0,0,0,0.5);
font-size: 92px;
}
span:hover {
transition: all 0.2s ease;
transform: scaleX(9.5) translateY(4px);
text-shadow:
0 1px 1px rgba(0,0,0,0.5);
}
body {
padding: 20px;
margin-left: 260px;
margin-top: -40px
}
Working Fiddle: https://jsfiddle.net/rittamdebnath/drefg8r4/
You can try using box-shadow to build a triangle instead of border. Then on :before or :after elements you can set an overlapping box-shadow, example by Chris Coyier:
http://codepen.io/chriscoyier/pen/bNZWzK
You can cuplicate your element, align it directly behind the default triangle and use the css filter propertie in conjunction with absolute position and the back element size.
.triangle-down {
position: relative;
width: 220px;
height: 220px;
box-sizing: border-box;
}
.arrows-down {
display: block;
height: auto;
max-width: 200px;
box-sizing: border-box;
}
.arrows-down-back {
position: absolute;
left: 0;
top: 0;
max-width: 200px;
filter: blur(20px) opacity(.3);
-webkit-filter: blur(20px) opacity(.3);
}
<div class="par">
<div class="triangle-down">
<svg class="arrows-down img-responsive" viewbox="0 0 102 102">
<path class="a1" d="M0 20 L30 52 L60 20"></path>
</svg>
<svg class="arrows-down img-responsive arrows-down-back" viewbox="0 0 102 102">
<path class="a1" d="M0 20 L30 52 L60 20"></path>
</svg>
</div>
</div>
You could relay only on a gradient to draw and blur(shadow) the triangle.
If you use vertical margin/padding in percentage, it takes the width for reference, so arrow is resized from width, not height of content.
div {
position:relative;
color:white;
background:#333;
text-align:center;
margin:1em;
margin-bottom:5.5%;
box-shadow: 0 0 5px #333;
}
div:after {
content:'';
display:block;
position:absolute;
top:100%;
left:0;
right:0;
padding-top:5%;
background:linear-gradient(to bottom left, #333 49%, transparent 51%) no-repeat 0 0, linear-gradient(to bottom right, #333 49%, transparent 51%) no-repeat top right;
background-size:50% 99%
}
html {/* demo purpose to show arrow box is translucide */
background:linear-gradient(45deg, yellow,gray,purple,white,lime, yellow,gray,purple,white,lime);
min-height:100%;
}
<div>responsive box arrow, resize me or add content </div>
<div>i can be replicated <hr/> maybe you should use a <code>class</code> there </div>

Hexagon with border and image

I have the following code for a hexagon. I need a border around the hexagon and an image as a background of the hexagon instead of a plain color.
body {
background: #ecf0f1;
}
#hex1 {
width: 200px;
height: 200px;
}
#color1 {
background-color: #D93;
}
.hexagon-wrapper {
text-align: center;
margin: 20px;
position: relative;
display: inline-block;
}
.hexagon {
height: 100%;
width: 57.735%;
display: inline-block;
}
.hexagon:before {
position: absolute;
top: 0;
right: 21.1325%;
background-color: inherit;
height: inherit;
width: inherit;
content: '';
transform: rotate(60deg);
}
.hexagon:after {
position: absolute;
top: 0;
right: 21.1325%;
background-color: inherit;
height: inherit;
width: inherit;
content: '';
transform: rotate(-60deg);
}
<div id="hex1" class="hexagon-wrapper">
<span id="color1" class="hexagon"></span>
</div>
Here is a link with the code
I would suggest changing your approach. An inline SVG would be the most fexible way to achieve this. And it isn't complicated, especialy for simple shapes like hexagons.
Here is an example using the polygon element, the image fills the polygon with the pattern element and the border is added with CSS (stroke and stroke-width properties) :
svg{
width:30%;
margin:0 auto;
}
#hex{
stroke-width:2;
stroke: teal;
}
<svg viewbox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="img" patternUnits="userSpaceOnUse" width="100" height="100">
<image xlink:href="https://farm4.staticflickr.com/3165/5733278274_2626612c70.jpg" x="-25" width="150" height="100" />
</pattern>
</defs>
<polygon id="hex" points="50 1 95 25 95 75 50 99 5 75 5 25" fill="url(#img)"/>
</svg>
One approach not yet covered, is to use CSS clip-path property, which is very simlar – but not quite the same as – the SVG solution offered by web-tiki.
Here we use a clip path to shape both the outer, and inner, elements, using a background-color on the outer element to emulate the border and set margin on the inner element to control the border-width:
html, body {
height: 100%;
background-color: black;
}
div.hexagon-wrapper {
display: inline-block;
-webkit-clip-path: polygon(50% 0, 100% 38%, 81% 100%, 19% 100%, 0 38%);
clip-path: polygon(50% 0, 100% 38%, 81% 100%, 19% 100%, 0 38%);
background-color: limegreen;
}
.hexagon-wrapper .hexagon {
display: block;
-webkit-clip-path: polygon(50% 0, 100% 38%, 81% 100%, 19% 100%, 0 38%);
clip-path: polygon(50% 0, 100% 38%, 81% 100%, 19% 100%, 0 38%);
margin: 3px;
}
<div class="hexagon-wrapper">
<img class="hexagon" src="http://lorempixel.com/150/150/people/1" />
</div>
JS Fiddle demo.
References:
clip-path (MDN).
clip-path (W3C).
I have edited your CSS to add borders over it.
http://codepen.io/anon/pen/MKaJJZ
In order to add background image:
Make the slices of the image and add it as background of each rectangle (3 rectangles you created in CSS) So that after joining 3 slices it becomes a single image
<div id="hex1" class="hexagon-wrapper">
<span id="color1" class="hexagon"></span>
</div>
body { background: #ecf0f1; }
#hex1 { width: 200px; height: 200px; }
#color1 { background-color: #D93; }
.hexagon-wrapper { text-align: center; margin: 20px; position: relative; display: inline-block; }
.hexagon { height: 100%; width: 60%; display: inline-block; border-top:5px solid red; border-bottom:4px solid red; }
.hexagon:before { position: absolute; top: 0; right: 20%; background-color: inherit; height: inherit; width: inherit; content: ''; transform: rotate(60deg); border-top:5px solid red; border-bottom:5px solid red; }
.hexagon:after { position: absolute; top: 0; right: 20.1%; background-color: inherit; height: inherit; width: inherit; content: ''; transform: rotate(-60deg); border-top:5px solid red; border-bottom:5px solid red; }

How to inscribe the following shape with CSS inside div?

FIDDLE
HTML
<div id="DiamondCenter">
<div id="triangle-topleft"></div>
</div>
CSS
#DiamondCenter {
position:fixed;
top:2%;
left:48%;
background: #24201a;
height:40px;
width:40px;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
z-index:20 !important;
}
#triangle-topleft {
width: 0;
height: 0;
border-top: 40px solid gray;
border-right: 40px solid transparent;
}
Using SVG:
While using SVG, you could make use of path and polyline elements to draw the required shape. As indicated by Paulie_D in comments, SVG is the better choice for such complex shapes instead of CSS (though this can be achieved with CSS also).
The approach is very simple and is as follows:
One path element for the top polygon which is drawn by joining the points at coordinates (0,50), (50,0), (100,50) and (50,70).
Another path element for the bottom polygon which is drawn by joining the points at (0,50), (50,70) and (100,50).
One polyline element for the orange border which is nothing but a line connecting (0,50), (50,70) and (100,50).
svg {
height: 100px;
width: 100px;
}
path#top {
fill: gray;
}
path#bottom {
fill: black;
}
polyline#border {
stroke: orange;
stroke-width: 2;
fill: none;
}
<svg viewBox="0 0 100 100">
<path id="top" d="M0,50 L50,0 100,50 50,70z" />
<path id="bottom" d="M0,50 L50,100 100,50 50,70z" />
<polyline id="border" points="0,50 50,70 100,50" />
</svg>
Using CSS:
You can achieve the shape provided in question by using 2 pseudo-elements which are both rotated and skewed. The dimension of each pseudo-element is calculated using Pythagoras theorem.
The shape produced using this method is responsive and can adapt to changes in dimension. Hover the shape within the snippet to see how it adapts.
*,
*:after,
*:before {
box-sizing: border-box;
}
#DiamondCenter {
position: fixed;
top: 2%;
left: 48%;
background: #24201a;
height: 40px;
width: 40px;
transform: rotate(45deg);
z-index: 20 !important;
overflow: hidden;
}
#DiamondCenter:after {
position: absolute;
content: '';
bottom: 0px;
left: -1px; /* half the width of border-left */
height: calc(100% / 1.414);
width: calc(100% / 1.414);
background: black;
border-left: 2px solid orange;
transform: rotate(40deg) skewX(-20deg);
transform-origin: bottom left;
}
#DiamondCenter:before {
position: absolute;
content: '';
top: -1px; /* half the width of border-top */
right: 0px;
height: calc(100% / 1.414);
width: calc(100% / 1.414);
background: black;
border-top: 2px solid orange;
transform: rotate(-40deg) skewY(-20deg);
transform-origin: top right;
}
/* Just for demo */
#DiamondCenter{
transition: all 1s;
}
#DiamondCenter:hover{
top: 5%;
height: 80px;
width: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id="DiamondCenter"></div>
In the below snippet, I have set different background colors for the pseudo-elements to illustrate how the shape is achieved.
*,
*:after,
*:before {
box-sizing: border-box;
}
#DiamondCenter {
position: fixed;
top: 2%;
left: 48%;
background: #24201a;
height: 40px;
width: 40px;
transform: rotate(45deg);
z-index: 20 !important;
overflow: hidden;
}
#DiamondCenter:after {
position: absolute;
content: '';
bottom: 0px;
left: -1px;
height: calc(100% / 1.414);
width: calc(100% / 1.414);
background: seagreen;
border-left: 2px solid orange;
transform: rotate(40deg) skewX(-20deg);
transform-origin: bottom left;
}
#DiamondCenter:before {
position: absolute;
content: '';
top: -1px;
right: 0px;
height: calc(100% / 1.414);
width: calc(100% / 1.414);
background: skyblue;
border-top: 2px solid orange;
transform: rotate(-40deg) skewY(-20deg);
transform-origin: top right;
}
/* Just for demo */
#DiamondCenter{
transition: all 1s;
}
#DiamondCenter:hover{
top: 5%;
height: 80px;
width: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id="DiamondCenter"></div>
This is quite a complicated shape to complete in CSS, but as shown by others it is possible.
A good alternative though would be to use SVG. Its a vector graphic so it scales brilliantly for responsiveness and is very well supported (CanIUse)
<svg width="50%" height="50%" viewBox="0 0 10 10">
<path d="M5,1
L9,5
L5,9
L1,5z" fill="grey" />
<path d="M1,5
L5,6
L9,5
L5,9z" stroke="orange" stroke-width=".1" stroke-dasharray="0,0,8.23,15" />
</svg>
You can create diamond shape using this css , suppose this is div where you want above shape id should be same as css (cut-diamond)
#cut-diamond {
border-style: solid;
border-color: transparent transparent red transparent;
border-width: 0 25px 25px 25px;
height: 0;
width: 50px;
position: relative;
margin: 20px 0 50px 0;
}
#cut-diamond:after {
content: "";
position: absolute;
top: 25px;
left: -25px;
width: 0;
height: 0;
border-style: solid;
border-color: red transparent transparent transparent;
border-width: 70px 50px 0 50px;
}
JSFiddle Demo

Shape resembling a compass pointer or inner part of a Safari logo

I am trying to make the below shape using only CSS. I know that achieving this shape using an image or SVG would be a lot easier but I am trying to achieve it with CSS for a proof of concept.
The below is the code that I have tried so far. It creates a diamond shape by using transform: rotate(45deg) but the diagonals are of the same length whereas the shape that I need has one very long diagonal and another very short.
.separator{
background: #555;
top: 40px;
padding-top: 0px;
margin: 0px 40px;
height: 100px;
width: 100px;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
}
Fiddle Demo
Is it possible to create the shape that I need using CSS?
Note: A similar question was asked earlier and was closed/deleted as "too broad" as it did not show any coding attempt. Posting a new question and self answering it based on this meta discussion. Please feel free to chip in with alternate solutions (or) edit the question to make it more useful for future readers.
For a needle resting on its tip
Yes, it is possible to create that shape using only CSS. You have to rotate the shape along both the Y-axis and the Z-axis to achieve it.
Rotating it along the Z-axis by 45 degrees will produce a diamond shape (as indicated in the question) and rotating it along the Y-axis by close to (but less than) 90 degrees will make only a part of the shape visible from the front and thereby would give it the appearance of having shorter diagonal lines (resembling a compass pointer).
Additionally adding a linear-gradient for the background and a inset box-shadow will help to achieve a shape that is a lot closer to the shape shown in question.
body {
background: #333;
font-family: Calibri;
font-size: 18px;
}
div {
height: 200px;
width: 150px;
display: inline-block;
vertical-align: middle;
color: white;
padding-top: 40px;
}
.separator {
background: #555;
top: 40px;
padding-top: 0px;
height: 160px;
width: 160px;
background-image: linear-gradient(-45deg, #555 0%, #555 40%, #444 50%, #333 97%);
box-shadow: inset 6px 6px 22px 8px #272727;
transform: rotateY(87deg) rotate(45deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div>
Some lengthy paragraph content which wraps around when it exceeds the width
</div>
<div class='separator'></div>
<div>
Some lengthy paragraph content which wraps around when it exceeds the width
</div>
For a needle resting on its base
For a needle that is resting on its base, the rotation should be along the X-axis and Z-axis instead of along Y-axis and Z-axis for the needle resting on its tip. Below is a sample snippet.
body {
background: #AAA;
font-family: Calibri;
font-size: 18px;
}
div {
height: 200px;
width: 150px;
display: inline-block;
vertical-align: middle;
color: white;
padding-top: 40px;
margin: 40px;
}
.separator {
background: #555;
top: 40px;
padding-top: 0px;
height: 160px;
width: 160px;
background-image: linear-gradient(-45deg, #555 0%, #555 40%, #444 50%, #333 97%);
box-shadow: inset 6px 6px 22px 8px #272727;
transform: rotateX(87deg) rotate(45deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='separator'></div>
Compass Pointer created using above method:
Here is a sample compass pointer (inspired in part by the Safari logo) created purely using CSS. The pointer or the needle inside is created using the method explained above.
.container {
position: relative;
height: 152px;
width: 152px;
padding: 10px;
border-radius: 50%;
background: radial-gradient(circle at 50% 50%, white 58%, #999 70%, #EEE 80%);
border: 1px solid #AAA;
}
.dial {
height: 150px;
width: 150px;
border-radius: 50%;
background: linear-gradient(#1ad4fd, #1d65f0 100%);
border: 1px solid #999;
position: relative;
animation: rotatedial 2s 6 alternate forwards;
}
.dial:after {
content: '';
position: absolute;
top: 25px;
left: 25px;
height: 100px;
width: 100px;
background-image: linear-gradient(-45deg, white 0%, white 47%, red 50%);
box-shadow: inset 0px 6px 22px 0px #CCC, inset -6px -6px 22px 0px #AAA;
transform: rotateY(85deg) rotate(45deg);
}
.dial:before {
content: '';
position: absolute;
top: 72px;
left: 70px;
height: 8px;
width: 8px;
background: radial-gradient(circle at 50% 50%, white 30%, grey 100%);
border: 1px solid #999;
border-radius: 50%;
z-index: 2;
}
.hands,
.hands-small {
position: absolute;
height: 150px;
width: 150px;
top: 11.25px;
left: 11px;
z-index: 0;
}
.hands:before,
.hands:after,
.hands .hand:before,
.hands .hand:after {
content: '';
position: absolute;
top: 0;
left: 74.5px;
width: 1px;
height: 12px;
background: #EEE;
border-radius: 4px;
box-shadow: 0px 138px #EEE;
transform-origin: 50% 75px;
}
.hands-small:before,
.hands-small:after,
.hands-small .hand-small:before,
.hands-small .hand-small:after {
content: '';
position: absolute;
top: 0;
left: 74.5px;
width: 1px;
height: 7px;
background: #EEE;
border-radius: 4px;
box-shadow: 0px 143px #EEE;
transform-origin: 50% 75px;
}
.hands:before {
transform: rotate(-45deg);
}
.hands:after {
transform: rotate(0deg);
}
.hand:before {
transform: rotate(45deg);
}
.hand:after {
transform: rotate(90deg);
}
.hands-small:before {
transform: rotate(-22.5deg);
}
.hands-small:after {
transform: rotate(22.5deg);
}
.hand-small:before {
transform: rotate(67.5deg);
}
.hand-small:after {
transform: rotate(112.5deg);
}
#keyframes rotatedial {
0% {
transform: rotate(35deg);
}
100% {
transform: rotate(15deg);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="container">
<div class="dial"></div>
<div class="hands">
<div class="hand"></div>
</div>
<div class="hands-small">
<div class="hand-small"></div>
</div>
</div>
If you stumbled on this page looking for a SVG implementation, have a look at the below snippet:
.separator {
position: relative;
width: 12px;
}
svg {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
path {
fill: url(#MyGradient);
}
path#shade {
stroke: #2E2E2E;
stroke-width: 3;
}
/* Just for the demo to style the divs and position */
body {
background: #333;
font-family: Calibri;
font-size: 18px;
}
.container {
display: flex;
}
.container > .content {
flex: 1;
flex-grow: 1;
color: white;
margin: 20px;
}
<div class='container'>
<div class='content'>Some lengthy paragraph content which wraps around when it exceeds the width.Some lengthy paragraph content which wraps around when it exceeds the width.Some lengthy paragraph content which wraps around when it exceeds the width.</div>
<div class='separator'>
<svg viewBox='0 0 10 200' preserveAspectRatio='none'>
<defs>
<linearGradient id="MyGradient" x1=' 50% ' y1='0% ' x2='50% ' y2='100% '>
<stop offset="0%" stop-color="#333" />
<stop offset="100%" stop-color="#555" />
</linearGradient>
</defs>
<path d='M0,100 5,0 10,100 z' id='shade' />
<path d='M0,100 5,0 10,100 5,200 z ' />
</svg>
</div>
<div class='content '>Some lengthy paragraph content which wraps around when it exceeds the width.Some lengthy paragraph content which wraps around when it exceeds the width.Some lengthy paragraph content which wraps around when it exceeds the width.</div>
</div>