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>