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
Related
I know i can create in CSS a lot of round corners, but i have never created something like this
I don't need styling for fonts, and heading only for left corner, it is possible to make it like this?
I know i can create moon like this, maybe this is the way?
#moon {
width: 80px;
height: 80px;
border-radius: 50%;
box-shadow: 15px 15px 0 0 red;
}
I think it has to be before pseudo class?
Any idea how to make it like my picture?
i guess you want something like this
jsfiddle
just create and element with :before, and make it oval.
to make it oval you need to set border-radius:100%; and the element should have a rectangle form... not a square form.
and then some minor position adjustments.
for this solution to work the background-color of the container where your element is situated ( in this case body ) needs to be the same as the background-color of the :before element
body {
background:#fff;
}
h2 {
color:#fff;
font-size:20px;
padding:10px;
width:200px;
text-align:right;
background:blue;
text-transform:uppercase;
position:relative;
}
h2:before {
position:absolute;
content:"";
background:#fff;
height:120%;
width:50px;
border-radius: 100%;
left:-25px;
top:-10%;
}
<h2>
Predictions
</h2>
You can use radial-gradient for background property of your element without any extra elements or pseudo-elements:
.shape {
width: 200px;
height: 50px;
padding: 0 20px;
line-height: 50px;
color: #ffffff;
text-align: right;
text-transform: uppercase;
font-size: 20px;
background: radial-gradient(circle 26px at 0% 50%, transparent, transparent 25px, #0000ff);
}
<div class="shape">Predictions</div>
More over, you can play with parameters of radial-gradient to get any required arc:
.shape {
width: 200px;
height: 50px;
padding: 0 20px;
line-height: 50px;
color: #ffffff;
text-align: right;
text-transform: uppercase;
font-size: 20px;
background: radial-gradient(circle 41px at -13% 50%, transparent, transparent 40px, #0000ff);
}
<div class="shape">Predictions</div>
Please look at the jsFiddle.
I need to create a solid color inset border. This is the bit of CSS I'm using:
border: 10px inset rgba(51,153,0,0.65);
Unfortunately that creates a 3D ridged border (ignore the squares and dark description box)
You could use box-shadow, possibly:
#something {
background: transparent url(https://i.stack.imgur.com/RL5UH.png) 50% 50% no-repeat;
min-width: 300px;
min-height: 300px;
box-shadow: inset 0 0 10px #0f0;
}
#something {
background: transparent url(https://i.stack.imgur.com/RL5UH.png) 50% 50% no-repeat;
min-width: 300px;
min-height: 300px;
box-shadow: inset 0 0 10px #0f0;
}
<div id="something"></div>
This has the advantage that it will overlay the background-image of the div, but it is, of course, blurred (as you'd expect from the box-shadow property). To build up the density of the shadow you can add additional shadows of course:
#something {
background: transparent url(https://i.stack.imgur.com/RL5UH.png) 50% 50% no-repeat;
min-width: 300px;
min-height: 300px;
box-shadow: inset 0 0 20px #0f0, inset 0 0 20px #0f0, inset 0 0 20px #0f0;
}
#something {
background: transparent url(https://i.stack.imgur.com/RL5UH.png) 50% 50% no-repeat;
min-width: 300px;
min-height: 300px;
box-shadow: inset 0 0 20px #0f0, inset 0 0 20px #0f0, inset 0 0 20px #0f0;
}
<div id="something"></div>
Edited because I realised that I'm an idiot, and forgot to offer the simplest solution first, which is using an otherwise-empty child element to apply the borders over the background:
#something {
background: transparent url(https://i.stack.imgur.com/RL5UH.png) 50% 50% no-repeat;
min-width: 300px;
min-height: 300px;
padding: 0;
position: relative;
}
#something div {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: 10px solid rgba(0, 255, 0, 0.6);
}
<div id="something">
<div></div>
</div>
Edited after #CoryDanielson's comment, below:
jsfiddle.net/dPcDu/2 you can add a 4th px parameter for the box-shadow that does the spread and will more easily reflect his images.
#something {
background: transparent url(https://i.stack.imgur.com/RL5UH.png) 50% 50% no-repeat;
min-width: 300px;
min-height: 300px;
box-shadow: inset 0 0 0 10px rgba(0, 255, 0, 0.5);
}
<div id="something"></div>
I would recomnend using box-sizing.
*{
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
-ms-box-sizing:border-box;
box-sizing:border-box;
}
#bar{
border: 10px solid green;
}
To produce a border inset within an element the only solution I've found (and I've tried all the suggestions in this thread to no avail) is to use a pseudo-element such as :before
E.g.
.has-inset-border:before {
content: " "; /* to ensure it displays */
position: absolute;
left: 10px;
right: 10px;
top: 10px;
bottom: 10px;
border: 4px dashed red;
pointer-events: none; /* user can't click on it */
}
The box-sizing property won't work, as the border always ends up outside everything.
The box-shadow options has the dual disadvantages of not really working and not being supported as widely (and costing more CPU cycles to render, if you care).
It's an old trick, but I still find the easiest way to do this is to use outline-offset with a negative value (example below uses -6px). Here's a fiddle of it—I've made the outer border red and the outline white to differentiate the two:
.outline-offset {
width:300px;
height:200px;
background:#333c4b;
border:2px solid red;
outline:2px #fff solid;
outline-offset:-6px;
}
<div class="outline-offset"></div>
If you want to make sure the border is on the inside of your element, you can use
box-sizing:border-box;
this will place the following border on the inside of the element:
border: 10px solid black;
(similar result you'd get using the additonal parameter inset on box-shadow, but instead this one is for the real border and you can still use your shadow for something else.)
Note to another answer above: as soon as you use any inset on box-shadow of a certain element, you are limited to a maximum of 2 box-shadows on that element and would require a wrapper div for further shadowing.
Both solutions should as well get you rid of the undesired 3D effects.
Also note both solutions are stackable (see the example I've added in 2018)
.example-border {
width:100px;
height:100px;
border:40px solid blue;
box-sizing:border-box;
float:left;
}
.example-shadow {
width:100px;
height:100px;
float:left;
margin-left:20px;
box-shadow:0 0 0 40px green inset;
}
.example-combined {
width:100px;
height:100px;
float:left;
margin-left:20px;
border:20px solid orange;
box-sizing:border-box;
box-shadow:0 0 0 20px red inset;
}
<div class="example-border"></div>
<div class="example-shadow"></div>
<div class="example-combined"></div>
I don't know what you are comparing to.
But a super simple way to have a border look inset when compared to other non-bordered items is to add a border: ?px solid transparent; to whatever items do not have a border.
It will make the bordered item look inset.
http://jsfiddle.net/cmunns/cgrtd/
Simple SCSS solution with pseudo-elements
Live demo: https://codepen.io/vlasterx/pen/xaMgag
// Change border size here
$border-width: 5px;
.element-with-border {
display: flex;
height: 100px;
width: 100%;
position: relative;
background-color: #f2f2f2;
box-sizing: border-box;
// Use pseudo-element to create inset border
&:before {
position: absolute;
content: ' ';
display: flex;
border: $border-width solid black;
left: 0;
right: 0;
top: 0;
bottom: 0;
border: $border-width solid black;
// Important: We must deduct border size from width and height
width: calc(100% - $border-width);
height: calc(100% - $border-width);
}
}
<div class="element-with-border">
Lorem ipsum dolor sit amet
</div>
You can do this:
.thing {
border: 2px solid transparent;
}
.thing:hover {
border: 2px solid green;
}
If box-sizing is not an option, another way to do this is just to make it a child of the sized element.
Demo
CSS
.box {
width: 100px;
height: 100px;
display: inline-block;
margin-right: 5px;
}
.border {
border: 1px solid;
display: block;
}
.medium { border-width: 10px; }
.large { border-width: 25px; }
HTML
<div class="box">
<div class="border small">A</div>
</div>
<div class="box">
<div class="border medium">B</div>
</div>
<div class="box">
<div class="border large">C</div>
</div>
I know this is three years old, but thought it might be helpful to someone.
The concept is to use the :after (or :before) selector to position a border within the parent element.
.container{
position:relative; /*Position must be set to something*/
}
.container:after{
position:relative;
top: 0;
content:"";
left:0;
height: 100%; /*Set pixel height and width if not defined in parent element*/
width: 100%;
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
-ms-box-sizing:border-box;
box-sizing:border-box;
border:1px solid #000; /*set your border style*/
}
You may use background-clip: border-box;
Example:
.example {
padding: 2em;
border: 10px solid rgba(51,153,0,0.65);
background-clip: border-box;
background-color: yellow;
}
<div class="example">Example with background-clip: border-box;</div>
So I was trying to have a border appear on hover but it moved the entire bottom bar of the main menu which didn't look all that good I fixed it with the following:
#top-menu .menu-item a:hover {
border-bottom:4px solid #ec1c24;
padding-bottom:14px !important;
}
#top-menu .menu-item a {
padding-bottom:18px !important;
}
I hope this will help someone out there.
Simpler + better | img tag | z-index | link image | "alt" attribute
I figured out a method where you do not need to use the image as a background image but use the img HTML tag inside the div, and using z-index of the div as a negative value.
Advantages:
The image can now become a link to a lightbox or to another page
The img:hover style can now change image itself, for example:
black/white to color, low to high opacity, and much more.
Animations of image are possible The image is more accessible because
of the alt tag you can use.
For SEO the alt tag is important for keywords
#borders {
margin: 10px auto;
width: 300px;
height: 300px;
position:relative;
box-shadow: inset 0 0 0 10px rgba(0, 255, 0, 0.5);
}
img {
position:absolute;
top:0;
bottom:0;
left:0;
right: 0;
z-index: -1;
}
<div id="borders">
<img src="https://i.stack.imgur.com/RL5UH.png">
</div>
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
I want to create a gradient arrow shape button with gradient border and 1px inner shadow from CSS.
I've created an image to show the button and the style rules:
This is what I have so far:
.button {
color: #FFF;
background-color: #D02180 !important;
background: -webkit-gradient(linear, 0 0, 0 100%, from(#f84aa4), to(#d02181));
background: -webkit-linear-gradient(#f84aa4, #d02181);
background: -moz-linear-gradient(#f84aa4, #d02181);
background: -o-linear-gradient(#f84aa4, #d02181);
background: linear-gradient(#f84aa4, #d02181);
padding: 5px 10px;
border-radius: 6px;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
border: 1px solid #ab1465;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.4) inset;
}
<a class="button">Next</a>
Cross-browser support is a main thing so it's also ok if everything can be done from CSS expect the gradient border. In this case the border will have one simple color — #ab1465.
The main problem starts with the gradient. I can make an arrow shape with the help of css pseudo elements, but I need a cross browser solution to have one continuous gradient for the whole arrow shape.
Gradient Arrow Button
Let's get creative!
This button has been created entirely with CSS — skew, border and gradient with pseudo elements. It looks like this:
It looks nice zoomed in and doesn't break:
This is the shape that creates it:
The shape is cut off with overflow: hidden on the parent.
The CSS
Create the angled shape and gradient with the :before.
The inner shadow is created with the :after using a simple border
The gradient is given an angle to match the direction of the pseudo elements rotation
Note the use of transform: translateZ(0). This prevents a jagged appearance of the rotated pseudo element. Currently the pseudo element is placed underneath the text with z-index: -1.
Complete Example
You will need to tinker with the fine details, but it should speak for itself. In order to take more text, the pseudo element with the gradient would need to be larger.
#import url(http://fonts.googleapis.com/css?family=Exo+2:300);
a {
color: #000;
text-decoration: none;
position: relative;
color: #FFF;
display: inline-block;
padding: 10px 40px 10px 10px;
border-radius: 5px;
overflow: hidden;
transform: translateZ(0);
font-family: 'Exo 2', sans-serif;
}
img {
position: relative;
z-index: -1;
}
a:before {
content: '';
display: block;
position: absolute;
top: 50%;
margin-top: -2.4em;
left: -20%;
width: 100%;
height: 200%;
background: #D02180 linear-gradient(130deg, rgba(248, 74, 165, 1) 30%, rgba(248, 74, 165, 1) 80%);
transform: rotate(55deg) skewX(20deg) translateZ(0);
z-index: -1;
}
a:after {
content: '';
display: block;
position: absolute;
top: 1px;
left: 1px;
width: 70%;
height: 100%;
transform: translateZ(0);
z-index: -1;
border-top: solid 1px #FFF;
border-radius: 5px 0;
opacity: 0.4;
}
Next
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.