Horizontal Line in Background using Css3 - css

How to implement this type of style to text using only css3, means a horizontal line in the middle of the tag... Can it be possible using pure css...
Here's my structure:-
<p class="datedAside">4 weeks ago</p>

You can achieve this with pure css using linear gradient as background:
<p class="datedAside">4 weeks ago</p>
<style>
p {
background: linear-gradient(180deg,
rgba(0,0,0,0) calc(50% - 1px),
rgba(192,192,192,1) calc(50%),
rgba(0,0,0,0) calc(50% + 1px)
);
}
</style>
https://jsfiddle.net/klesun/aujrkpLk/

Here's one way to do it by adding a span inside the p.
HTML:
<p class="datedAside"> <span> 4 weeks ago </span> </p>​
CSS:
p {background: #000; height:1px; margin-top:10px;}
p span{background: #fff; padding:10px; position:relative; top:-10px; left: 20px}​
DEMO: http://jsfiddle.net/9GMJz/

One of the simplest way I know, you can achieve this like this:
HTML
<p>Your text goes here</p>
<hr>
​
CSS
p {
background: #fff; // or whatever is your bg-color
display:inline-block;
padding-right: 1em;
line-height: 1.2em;
}
p+hr {
margin-top: -0.6em;
}
JSFiddle
http://jsfiddle.net/cTMXa/1/

You can do it with a 1% gradient like this
.datedAside {
background: linear-gradient(0deg, transparent 49%, #000 50%, transparent 51%);
}
.datedAside span{
background: #FFF;
padding: 0 0.5rem;
}
You'll nedd the extra span to be the same background color as the background of the component to make it look like it has "deleted" the line going behind the text.

You could add a pseudo-element to the paragraph selector like so:
p {
::before {
border-top: 10px solid #0066a4;
content:"";
margin: 0 auto; /* this centers the line to the full width specified */
position: absolute; /* positioning must be absolute here, and relative positioning must be applied to the parent */
top: 12px; left: 0; right: 0; bottom: 0;
z-index: -1;
}
}
See this CodePen by Eric Rasch for a working example: https://codepen.io/ericrasch/pen/Irlpm

An alternative with flex and ::before and ::after.
With this solution, you don't need to use a background for the content.
With this HTML markup :
<p class="datedAside"><span>4 weeks ago</span></p>
And this CSS :
.datedAside {
display: flex;
flex-flow: nowrap;
justify-content: space-between;
align-items: center;
}
.datedAside span {
padding: 1em;
}
.datedAside::before,
.datedAside::after {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
content: " ";
height: 0px;
border-bottom: 1px solid black;
}

Artur's solution creates a line however if you increase the px value it becomes clear that the line is still a gradient. This can be fixed by using a start and stop for the middle colour as such:
p {
background: linear-gradient(to bottom, white calc(50% - 1px), black calc(50% - 1px) calc(50% + 1px), white calc(50% + 1px));
}
The line will be double the thickness of the px value given (due to +px -px) so the above gives a horizontal 2px line across the center of the element.

Another way would be to use the linear-gradient as a background and place it in the middle of the paragraph or div.
p {
background-image: linear-gradient(red, red);
background-size: 100% 1px; /* add your height of the line here*/
background-repeat: no-repeat;
background-position: 50% 50%; /*place it in the middle */
}

I was update from fork for my solution.
http://jsfiddle.net/0f9catjy/
Html Block
<h1 class="lined"><span>H1 Lined Sample</span></h2>
<h2 class="lined"><span>H2 Lined Sample</span></h2>
<h3 class="lined"><span>H3 Lined Sample</span></h2>
<h1 class="lined lined-double"><span>H1 Double-lined Sample</span></h1>
<h2 class="lined lined-double"><span>H1 Double-lined Sample</span></h2>
Css Block
/**
* Horizontal Type Line Behind Text
* Inspired by this discussion # CSS-Tricks: http://css-tricks.com/forums/discussion/comment/51357#Comment_51357
* Available on jsFiddle: http://jsfiddle.net/ericrasch/jAXXA/
* Available on Dabblet: http://dabblet.com/gist/2045198
* Available on GitHub Gist: https://gist.github.com/2045198
*/
h1, .h1 { font-size: 2.5rem; }
h2, .h2 { font-size: 2rem; }
h3, .h3 { font-size: 1.75rem; }
h4, .h4 { font-size: 2.5rem; }
h5, .h5 { font-size: 1.25rem; }
h6, .h6 { font-size: 1rem; }
h1.lined, h2.lined, h3.lined, h4.lined, h5.lined, h6.lined
{
font-family: sans-serif;
position: relative;
text-align: left;
z-index: 1;
}
h1.lined:before,
h2.lined:before,
h3.lined:before,
h4.lined:before,
h5.lined:before,
h6.lined:before
{
border-top: 2px solid #dfdfdf;
content: "";
margin: 0 auto;
position: absolute;
top: calc(50% - 2px);
left: 0;
right: 0;
bottom: 0;
width: 95%;
z-index: -1;
}
h1.lined span,
h2.lined span,
h3.lined span,
h4.lined span,
h5.lined span,
h6.lined span
{
background: #fff;
padding: 0 15px;
}
h1.lined-double:before,
h2.lined-double:before,
h3.lined-double:before,
h4.lined-double:before,
h5.lined-double:before,
h6.lined-double:before
{
border-top: none;
}
h1.lined-double:after,
h2.lined-double:after,
h3.lined-double:after,
h4.lined-double:after,
h5.lined-double:after,
h6.lined-double:after
{
border-bottom: 1px solid blue;
-webkit-box-shadow: 0 3px 0 0 red;
-moz-box-shadow: 0 3px 0 0 red;
box-shadow: 0 3px 0 0 red;
content: "";
margin: 0 auto;
position: absolute;
top: calc(50% - 6px);
left: 0;
right: 0;
width: 95%;
z-index: -1;
transform: translateY(calc(-50% + 3px));
}
/** END
* Horizontal Type Line Behind Text
*/

Related

How to create Button with cut edges? [duplicate]

I'm looking for an easy way with a single tag (just <a>)to create a skew effect on the borders, but keep the text the way it is.
I would know how do with a span in- or outside, but I don't want to have additional, pretty much zero meaning HTML on the page.
Example below.
You can unskew the child element i.e. provide the opposite skew co-ordinates as you specified for the parent.
Here is a working example
Suppose you have below as you html,
<div class="btn">
<button><div class="btn-text">Click</div></button>
</div>
If we skew the parent element by 20deg then we should skew the child element by -20deg as,
.btn {
-ms-transform: skewX(20deg); /* IE 9 */
-webkit-transform: skewX(20deg); /* Safari */
transform: skewX(20deg);
}
.btn-text {
-ms-transform: skewX(-20deg); /* IE 9 */
-webkit-transform: skewX(-20deg); /* Safari */
transform: skewX(-20deg);
padding: 20px;
}
You can simply accompish desired effect using CSS triangle tricks.
Just add some styles for the ::before and :: after pseudo-classes.
.skewed_button {
background: #32CD32;
color: #000;
text-decoration: none;
font-size: 20px;
display: inline-block;
height: 30px;
margin-left: 15px;
padding: 6px 10px 0;
}
.skewed_button::before {
content: "";
float: left;
margin: -6px 0 0 -25px;
border-left: 15px solid transparent;
border-bottom: 36px solid #32CD32;
height: 0px;
}
.skewed_button::after {
content: "";
float: right;
margin: -6px -25px 0 0 ;
border-left: 15px solid #32CD32;
border-bottom: 36px solid transparent;
height: 0px;
}
Some Text
You can also use clip-path for this, eg:
clip-path: polygon(14px 0%, 100% 0%, calc(100% - 14px) 100%, 0% 100%);
.skewed_button {
background: yellow;
text-decoration: none;
display: inline-block;
padding: 10px 20px;
clip-path: polygon(14px 0%, 100% 0%, calc(100% - 14px) 100%, 0% 100%);
}
Some Text
One solution is to use css triangles on :before and :after. This solution leaves the cleanest HTML.
This jsfiddle demonstrates
.is-skewed {
width: 80px;
height: 40px;
background-color: #f07;
display: block;
color: #fff;
margin-left: 40px;
}
.is-skewed:before,
.is-skewed:after {
content: '';
width: 0;
height: 0;
}
.is-skewed:before {
border-bottom: 40px solid #f07;
border-left: 20px solid transparent;
float:left;
margin-left: -20px;
}
.is-skewed:after {
border-top: 40px solid #f07;
border-right: 20px solid transparent;
float:right;
margin-right: -20px;
}
CSS triangles use thick borders on elements with 0 dimensions with the points at which the borders meet providing the diagonal line required for a triangle (a good visualisation is to look at the corner of a picture frame, where the two borders meet and create triangles). It's important that one border is transparent and one coloured and that they are adjacent (i.e. left and top, not left and right). You can adjust the size, orientation and the lengths of the sides by playing with the border sizes.
For your button, we also use floats and negative margins to pull them outside of the element and line them up right. Position absolute and negative left and right values would also be a good solution to positioning
You can also do :hover states
.is-skewed:hover {
background-color: #40f;
}
.is-skewed:hover:after {
border-top-color: #40f;
}
.is-skewed:hover:before {
border-bottom-color: #40f;
}
It's important to note the use of background-color and border-color and also that the :hover comes first in all the relevant selectors. If the hover came second this would happen

CSS - Custom cursor that changes depending on hovered element flickers when moving left to right but not right to left

I am trying to create a custom cursor that changes when hovering over a <div>, but there is a flicker when moving left to right across it, but not when moving right to left. Why this is happening and what I can do to fix it?
document.addEventListener('mousemove', (ev) => cursorMove(ev));
function cursorMove(ev) {
let circle = document.getElementById('circle');
let posY = ev.clientY;
let posX = ev.clientX;
circle.style.top = posY + 'px';
circle.style.left = posX + 'px';
}
body {
margin: 0;
height: 100vh;
background-color: #acd1d2;
position: relative;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
}
#wrapper {
position: relative;
width: 70%;
height: 80%;
}
.box {
height: 25%;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
#box-1 {
background-color: #e8edf3;
}
#box-1:hover ~ #circle {
background-color: #e6cf8b;
box-shadow:inset 0em -0.3em 0.4em 0.2em #ca9e03a6;
}
#box-2 {
background-color: #e6cf8b;
}
#box-2:hover ~ #circle {
background-color: transparent;
border: 3px solid #E91E63;
}
#box-3 {
background-color: #b56969;
}
#box-3:hover ~ #circle {
height: 1em;
width: 1em;
background-color: #e6cf8b;
}
#box-4 {
background-color: #22264b;
color: white;
}
#box-4:hover ~ #circle {
background-image: linear-gradient(to top, #fbc2eb 0%, #a6c1ee 100%);
}
#circle {
position: fixed;
border-radius: 50%;
z-index: 5;
height: 32px;
width: 32px;
background-color: white;
}
<div id="wrapper">
<div id="box-1" class="box">Sphere</div>
<div id="box-2" class="box">Circle outline</div>
<div id="box-3" class="box">Circle pin</div>
<div id="box-4" class="box">Circle color gradient</div>
<div id="circle"></div>
</div>
That's because your mouse moves faster than the circle and you hover over it, so the styles that apply to it are the same ones than when the cursor is on the background green/blue-ish area of the page.
You can fix that by adding pointer-events: none to the circle so that it feels a bit like this:
Ok, where were we? Oh yes... So you should use position: fixed instead of absolute (as you really want your cursor to be positioned relative to the top-left corner of the viewport) and probably window.requestAnimationFrame to get a smoother animation and translate3d(0, 0, 0) to promote the element to its own layer and enable hardware-accelerated rendering, which will also contribute to make it feel smoother.
You could also hide the default cursor with cursor: none and center the circle where the arrowhead of the cursor is to make it feel just like a real cursor.
const circle = document.getElementById('circle');
const circleStyle = circle.style;
document.addEventListener('mousemove', e => {
window.requestAnimationFrame(() => {
circleStyle.top = `${ e.clientY - circle.offsetHeight/2 }px`;
circleStyle.left = `${ e.clientX - circle.offsetWidth/2 }px`;
});
});
body {
margin: 0;
height: 100vh;
background-color: #acd1d2;
position: relative;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
cursor: none;
}
#wrapper {
position: relative;
width: 70%;
height: 80%;
}
#circle {
position: fixed;
border-radius: 50%;
z-index: 5;
height: 32px;
width: 32px;
background-color: white;
pointer-events: none;
transition:
background ease-in 10ms,
box-shadow ease-in 150ms,
transform ease-in 150ms;
/* Promote it to its own layer to enable hardware accelerated rendering: */
transform: translate3d(0, 0, 0);
}
.box {
height: 25%;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
#box-1 {
background-color: #e8edf3;
}
#box-1:hover ~ #circle {
background-color: #e6cf8b;
box-shadow: 0 0 0 0 transparent, inset 0em -0.3em 0.4em 0.2em #ca9e03a6;
}
#box-2 {
background-color: #e6cf8b;
}
#box-2:hover ~ #circle {
background-color: transparent;
/* Use box-shadow instead of border to avoid changing the dimensions of the
cursor, which will make it be off-center until the mouse moves again: */
aborder: 3px solid #E91E63;
box-shadow: 0 0 0 3px #E91E63;
}
#box-3 {
background-color: #b56969;
}
#box-3:hover ~ #circle {
background-color: #e6cf8b;
/* Change its size with scale() instead of width and height for better
performance performance: */
transform: scale(0.5) translate3d(0, 0, 0);
}
#box-4 {
background-color: #22264b;
color: white;
}
#box-4:hover ~ #circle {
background-image: linear-gradient(to top, #fbc2eb 0%, #a6c1ee 100%);
}
<div id="wrapper">
<div id="box-1" class="box">Sphere</div>
<div id="box-2" class="box">Circle outline</div>
<div id="box-3" class="box">Circle pin</div>
<div id="box-4" class="box">Circle color gradient</div>
<div id="circle"></div>
</div>
Here you can see another cool example I made of a custom cursor using CSS that resembles a torch: How to darken a CSS background image but keep area around cursor brighter.
Also, you can check out the cursor on my website, which is quite similar to what you have done as it has animations/transitions between its different shapes or states.
🚀 Check it out here: https://gmzcodes.com/.
👨‍💻 Check the code here: https://github.com/Danziger/gmzcodes

CSS: Skew a buttons border, not the text

I'm looking for an easy way with a single tag (just <a>)to create a skew effect on the borders, but keep the text the way it is.
I would know how do with a span in- or outside, but I don't want to have additional, pretty much zero meaning HTML on the page.
Example below.
You can unskew the child element i.e. provide the opposite skew co-ordinates as you specified for the parent.
Here is a working example
Suppose you have below as you html,
<div class="btn">
<button><div class="btn-text">Click</div></button>
</div>
If we skew the parent element by 20deg then we should skew the child element by -20deg as,
.btn {
-ms-transform: skewX(20deg); /* IE 9 */
-webkit-transform: skewX(20deg); /* Safari */
transform: skewX(20deg);
}
.btn-text {
-ms-transform: skewX(-20deg); /* IE 9 */
-webkit-transform: skewX(-20deg); /* Safari */
transform: skewX(-20deg);
padding: 20px;
}
You can simply accompish desired effect using CSS triangle tricks.
Just add some styles for the ::before and :: after pseudo-classes.
.skewed_button {
background: #32CD32;
color: #000;
text-decoration: none;
font-size: 20px;
display: inline-block;
height: 30px;
margin-left: 15px;
padding: 6px 10px 0;
}
.skewed_button::before {
content: "";
float: left;
margin: -6px 0 0 -25px;
border-left: 15px solid transparent;
border-bottom: 36px solid #32CD32;
height: 0px;
}
.skewed_button::after {
content: "";
float: right;
margin: -6px -25px 0 0 ;
border-left: 15px solid #32CD32;
border-bottom: 36px solid transparent;
height: 0px;
}
Some Text
You can also use clip-path for this, eg:
clip-path: polygon(14px 0%, 100% 0%, calc(100% - 14px) 100%, 0% 100%);
.skewed_button {
background: yellow;
text-decoration: none;
display: inline-block;
padding: 10px 20px;
clip-path: polygon(14px 0%, 100% 0%, calc(100% - 14px) 100%, 0% 100%);
}
Some Text
One solution is to use css triangles on :before and :after. This solution leaves the cleanest HTML.
This jsfiddle demonstrates
.is-skewed {
width: 80px;
height: 40px;
background-color: #f07;
display: block;
color: #fff;
margin-left: 40px;
}
.is-skewed:before,
.is-skewed:after {
content: '';
width: 0;
height: 0;
}
.is-skewed:before {
border-bottom: 40px solid #f07;
border-left: 20px solid transparent;
float:left;
margin-left: -20px;
}
.is-skewed:after {
border-top: 40px solid #f07;
border-right: 20px solid transparent;
float:right;
margin-right: -20px;
}
CSS triangles use thick borders on elements with 0 dimensions with the points at which the borders meet providing the diagonal line required for a triangle (a good visualisation is to look at the corner of a picture frame, where the two borders meet and create triangles). It's important that one border is transparent and one coloured and that they are adjacent (i.e. left and top, not left and right). You can adjust the size, orientation and the lengths of the sides by playing with the border sizes.
For your button, we also use floats and negative margins to pull them outside of the element and line them up right. Position absolute and negative left and right values would also be a good solution to positioning
You can also do :hover states
.is-skewed:hover {
background-color: #40f;
}
.is-skewed:hover:after {
border-top-color: #40f;
}
.is-skewed:hover:before {
border-bottom-color: #40f;
}
It's important to note the use of background-color and border-color and also that the :hover comes first in all the relevant selectors. If the hover came second this would happen

Why the text keeps stay out of my bubble box?

I can't understand why the text I'm trying to get in the bubble box won't be there.
Here is the link to a picture of what I see
I'm super newbie and this might be a very stupid question, but I spent like 40 minutes trying to figure out what's wrong.
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
.bubble
{
position: absolute;
width: 230px;
height: 33px;
text-align: left;
font-size: 10px;
line-height: 100px;
background-color: #00ff00;
border-radius: 10px;
margin-top: 100px;
margin-left: 200px;
}
.bubble:after
{
content: '';
position: absolute;
width: 0;
height: 0;
left: 20px;
top: 33px;
border: 22px solid;
border-color: #00ff00 transparent transparent #00ff00;
}
</style>
</head>
<div class="bubble">im lemon im a little spaghetti</div>
</html>
Help
You should define line-height: 33px, because that is the height of your bubble
See fiddle
I suggest you add a bit of padding, so that the text won't be stuck at the left border of the bubble. Like that :
padding: 0 5px;
That will add 5px of padding to the left and to the right, that is a shorthand for :
padding: 0 5px 0 5px; which is itself a shorthand for
padding-top: 0;
padding-right: 5px;
padding-bottom: 0;
padding-left: 5px;
See updated fiddle
Looks like its overlapping. You should look at this example, there are variety of layouts and other css options to accomplish what you're trying to do covering multiple browsers.
http://nicolasgallagher.com/pure-css-speech-bubbles/demo/
Here is the CSS for the first bubble text:
.triangle-isosceles {
position:relative;
padding:15px;
margin:1em 0 3em;
color:#000;
background:#f3961c; /* default background for browsers without gradient support */
/* css3 */
background:-webkit-gradient(linear, 0 0, 0 100%, from(#f9d835), to(#f3961c));
background:-moz-linear-gradient(#f9d835, #f3961c);
background:-o-linear-gradient(#f9d835, #f3961c);
background:linear-gradient(#f9d835, #f3961c);
-webkit-border-radius:10px;
-moz-border-radius:10px;
border-radius:10px;
}
/* Variant : for top positioned triangle
------------------------------------------ */
.triangle-isosceles.top {
background:-webkit-gradient(linear, 0 0, 0 100%, from(#f3961c), to(#f9d835));
background:-moz-linear-gradient(#f3961c, #f9d835);
background:-o-linear-gradient(#f3961c, #f9d835);
background:linear-gradient(#f3961c, #f9d835);
}
The complete CSS:
http://nicolasgallagher.com/pure-css-speech-bubbles/demo/default.css
Basically you'd put the text inside the paragraph tag by calling the class:
<p class="triangle-isosceles">This only needs one HTML element.</p>
#ref: http://nicolasgallagher.com/pure-css-speech-bubbles/demo/

Css3 donut menu

Hi I would like to implement a donut menu like this one http://dribbble.com/shots/610433-Wheel-Nav I know there is a simple way to do a donuts in css3.
.doughnut {
border: 50px solid #f00;
border-radius: 100px;
height:100px;
width:100px;
}
BUT of course this only make the donut without any elements inside of it. I'm wonder if it's anyway to do it only with css3, any ideas of how to start? if is not possible with only css i will jump into javascript area...
My attempt to reproduce that image with CSS:
live demo
Result:
HTML:
<ul class='menu circ-menu'>
<li class='menu-item'>
<a href='#'>☊</a>
</li>
<li class='menu-item selected'>
<a href='#'>☁☀</a>
<ul class='menu submenu'>
<li><a href='#'>☂</a></li><!--
--><li><a href='#'>☁</a></li><!--
--><li><a href='#'>☃</a></li>
</ul>
</li>
<li class='menu-item'>
<a href='#'>✦</a>
</li>
</ul>
CSS:
.menu { padding: 0; list-style: none; }
.menu a {
display: block;
color: #666561;
font: 900 2em/3.2 monospace;
text-decoration: none;
text-shadow: 0 1px white;
}
.circ-menu {
overflow: hidden;
position: relative;
margin: 1em auto;
padding: 5em 0 0;
width: 20em; height: 10em;
box-shadow: 0 .5em .5em -.5em;
}
.menu-item {
overflow: hidden;
position: absolute;
z-index: 0;
left: -50%; bottom: 0;
width: 20em; height: 20em;
transform-origin: 100% 100%;
}
/* === style the menu items (slices) === */
/* three slices making up half a circle mean that a slice is going to have a central_angle = 60deg */
.menu-item:first-child {
transform: skewX(30deg) /* 90deg - central_angle */;
}
.menu-item:nth-child(2) {
/* rotate by the value of the central angle multiplied with how many slices are before */
transform:
rotate(60deg) /* 60deg = 1*central angle */
skewX(30deg) /* 90deg - central_angle */;
}
.menu-item:last-child {
transform:
rotate(120deg) /* 120deg = 2*central angle */
skewX(30deg) /* 90deg - central_angle */;
}
/* === contents of the menu items === */
.menu-item > * {
position: absolute;
top: 55%; left: 55%;
width: 90%; height: 90%;
text-align: center;
}
.menu-item > a {
border-radius: 50%;
box-shadow: 0 0 0 .2em #aaa497,
0 0 .5em .2em black;
transform:
skewX(-30deg) /* unskew */
rotate(-60deg);
background: #f8f4ef;
background:
radial-gradient(transparent 39%, #f7f3ee 40%);
}
.selected > a { z-index: 1; }
.selected > a, .menu a:hover {
color: #e96429;
}
.selected > a, .menu-item > a:hover {
box-shadow: 0 0 0 .2em #e96429,
0 0 .5em .2em black;
background:
linear-gradient(60deg, #e96429 31%, rgba(247, 243, 238, 0) 33%),
linear-gradient(-60deg, #e96429 31%, rgba(247, 243, 238, 0) 33%),
radial-gradient(transparent 39%, #f7f3ee 40%);
background-size: 100% 26%, 100% 26%, 100% 100%;
}
.submenu {
z-index: 0;
transform:
skewX(-30deg) /* unskew */
rotate(-60deg)
translateY(-5.25em);
}
.submenu li {
display: inline-block;
position: relative;
border-top: solid 1px #666561;
border-bottom: solid 1px #666561;
width: 3.2em; height: 3.2em;
background: #f7f3ee;
}
.submenu li:before {
position: absolute;
bottom: 0;
width: 100%; height: .2em;
background: #666561;
content: '';
}
.submenu a {
line-height: 2
}
.submenu li:first-child {
border-radius: .3em 0 0 .3em;
border-left: solid 1px #666561;
}
.submenu:after {
position: absolute;
z-index: -1;
top: 2.5em; left: 50%;
margin: 0 -.6em;
width: 1.2em; height: 1.2em;
transform: rotate(-30deg) skewX(30deg);
background: #666561;
content: '';
}
.submenu li:last-child {
border-radius: 0 .3em .3em 0;
border-right: solid 1px #666561;
}
.circ-menu:before, .circ-menu:after {
position: absolute;
z-index: 1;
bottom: -7.071em; left: 14.645%;
width: 14.142em; height: 14.142em;
border-radius: 50%;
content: '';
}
.circ-menu:before {
bottom: -5em; left: 5em;
width: 10em; height: 10em;
box-shadow: inset 0 0 .75em black,
0 0 .5em .2em #f7f3ee;
}
.circ-menu:after {
bottom: -1em; left: 9em;
width: 2em; height: 2em;
box-shadow: 0 0 .4em dimgrey,
0 0 0 .75em #e27447,
0 0 .4em .75em dimgrey,
0 0 0 2em #f7f3ee,
0 0 .4em 2em dimgrey;
background: #f7a480;
}
The idea is pretty simple. You start with a list structure, just like you would do for every menu.
<ul class='menu-circ'>
<li class='menu-item'><a href='#'>boo</a></li>
<!-- the other list items -->
</ul>
Explaining the basic idea
You give the container .menu-circ position: relative and you absolutely position its children (the menu items) such that one of their corners is at the centre (of .menu-circ). Then you set the transform-origin for .menu-item to be in that corner.
In this case, I've chosen the bottom right corner to be at the centre (transform-origin: right bottom is equivalent to transform-origin: 100% 100%), but it doesn't really matter, you can choose whichever corner you want to put at the centre and set the transform-origin there.
You then need to decide on the value of the central angle for each slice that a menu item forms. In this case, it was easy - there were three slices for half a circle, half a circle means 180deg, so assuming that I want 3 equal slices, the central angle for each is 180deg/3 = 60deg.
Having decided on that, you now need to make the sides that meet at the centre of the parent (right and bottom sides in this case) form an angle of 60deg. You do that by applying a skew transform, the skew angle being 90deg-60deg = 30deg:
transform: skewX(30deg);
But this still leaves all the menu items in the position of the first one. So for all the menu items but the first one, you also need to rotate the by the value of the central angle times how many items there are before. This means that you'll have:
.menu-item:first-child { transform: skewX(30deg); } /* no items before */
.menu-item:nth-child(2) { transform: rotate(60deg) /* 1*60deg */ skewX(30deg); }
.menu-item:nth-child(3) { transform: rotate(120deg) /* 2*60deg */ skewX(30deg); }
This positions all the menu items where they should be, but now their contents are skewed. So you need to "unskew" them. By that, I mean that you apply a skew transform with the opposite angle. In this case, unskewing means applying skewX(-30deg).
Still, the angle for the content is not right. You need to rotate it by half the central angle minus 90deg in this case. This means by 60deg/2 - 90deg = 30deg - 90deg = -60deg.
The content (link in this case) should also be absolutely positioned such that its centre is at the point where you've set the transform-origin for its parent (.menu-item) you can give it any size you want, but if you want it to be circular, then you'll have to give it equal width and height and make sure that they aren't more than twice those of its parent (.menu-item).
Finally, you set overflow: hidden on .menu-item and you have a pie menu. If you want to cover the central part, you use a pseudo-element on the menu (.menu-circ).
Have a look at some of these properties:
CSS 3 Transform - for the element rotations - W3
CSS 3 Transitions - to smoothly rotate the dial I suppose - W3
CSS Hover selector - for the popup - W3
CSS 3 Clip - to shape the elements - W3
This tutorial on creating css3 pie charts could help you: http://www.kylejlarson.com/blog/2011/how-to-create-pie-charts-with-css3/.
You could make all of the pie wedges be your buttons, then superimpose a smaller circle on the center of the wheel.

Resources