can attribute selectors be used with styled-components? - css

after doing a bit of research, I could not find information regarding the usage of attribute selectors (that is, [attr=value]) in styled-components. however, I still imagine it is highly possible for styled-components to support attribute selectors... but should it not, what are some equivalents of it?
for instance, if I have the code below
.squares li[data-level='1'] {
background-color: var(--light);
}
.squares li[data-level='2'] {
background-color: var(--medium);
}
.squares li[data-level='3'] {
background-color: var(--dark);
}
.squares li[data-level='4'] {
background-color: var(--darkest);
}
how do I achieve it via styled-components?

It is very simple, need create styled component, example "Squares" and define styles for nested list items with attribute "data-value='N'"
const Squares = styled.div`
li[data-level='1'] {
background-color: var(--light);
}
li[data-level='2'] {
background-color: var(--medium);
}
li[data-level='3'] {
background-color: var(--dark);
}
li[data-level='4'] {
background-color: var(--darkest);
}
`

I figured it out; this is what I did:
const SquareListItem = styled.li`
border-radius: 3px;
border: 1px rgba(27, 31, 35, 0.06) solid;
background-color: ${colour[0]};
&[data-level='1'] {
background-color: ${colour[1]};
}
&[data-level='2'] {
background-color: ${colour[2]};
}
&[data-level='3'] {
background-color: ${colour[3]};
}
&[data-level='4'] {
background-color: ${colour[4]};
}
/* tooltip */
&[data-tooltip] {
position: relative;
cursor: pointer;
}
&[data-tooltip]:before,
&[data-tooltip]:after {
visibility: hidden;
opacity: 0;
pointer-events: none;
}
&[data-tooltip]:before {
position: absolute;
z-index: 999;
bottom: 150%;
left: 100%;
margin-bottom: 5px;
margin-left: -90px;
padding: 7px;
width: 150px;
border-radius: 3px;
background-color: #000;
background-color: hsla(0, 0%, 20%, 0.9);
color: #fff;
content: attr(data-tooltip);
text-align: center;
font-size: 10px;
line-height: 1.2;
}
&[data-tooltip]:after {
position: absolute;
bottom: 150%;
left: 50%;
margin-left: -5px;
width: 0;
border-top: 5px solid hsla(0, 0%, 20%, 0.9);
border-right: 5px solid transparent;
border-left: 5px solid transparent;
content: ' ';
font-size: 0;
line-height: 0;
z-index: inherit;
}
/* show tooltip content on hover */
&[data-tooltip]:hover:before,
&[data-tooltip]:hover:after {
visibility: visible;
opacity: 1;
}
`

Related

Applying CSS animations to a square(dynamically changing the border size and square size)

The screenshot attached explains everything about the desired effect. I was thinking to decrease the border width from 4px to 3px to 2px , I don't want to apply ease-in/ease out effect. As of now, when I hover, it looks like this. I want to change this box through the effect displayed in the first screenshot.
For reference,
I am posting the code below:
&__link {
#include font-text(default, menuitem);
#include token(font-size, sidenav, default);
background-image: none;
text-transform: uppercase;
padding: 1rem;
margin: 0;
&:before {
position: absolute;
right: 1.3rem;
top: 2rem;
width: 1px;
content: '';
background: #fff;
height: 100%;
opacity: 0.3;
}
&:after {
display: inline-block;
vertical-align: middle;
position: relative;
content: '';
width: 10px;
height: 10px;
outline: 1px solid #fff;
top: -1px;
}
&:hover {
#include font-text(default, menuitem);
#include token(font-size, sidenav, hover);
font-weight: 600;
margin: 0;
padding: 1rem;
&:after {
background: white;
box-shadow: 0 0 10px 1px rgba(255, 255, 255, 1);
}
}
}
&:after represents the code for the box. Thanks in advance.
<div class="box">
</div>
.box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
height: 200px;
width: 200px;
text-decoration: none;
background-color: white;
background-image: linear-gradient(#000, #000);
border: 1px solid black;
background-position: 50% 50%;
background-repeat: no-repeat;
background-size: 0% 0%;
transition: .5s;
}
.box:hover {
background-size: 95% 95%;
}
Didnt understand the question too well but this does the attached screenshot animation
Try it - you need to set animations, bcz you want several situations for single event (hover)
Replace these blocks
&:after {
display: inline-block;
vertical-align: middle;
position: relative;
content: '';
width: 0px;
height: 0px;
top: -1px;
background: white;
border: 7px solid #fff;
}
&:hover:after {
animation: sqr .3s linear;
animation-fill-mode: forwards;
}
#keyframes sqr {
30%{
border: 5.5px solid #fff;
width: 3px; height: 3px;
background: black;
}
80%{
border: 4px solid #fff;
width: 6px;
height: 6px;
background: black;
}
100%{
border: 3px solid #fff;
width: 8px;
height: 8px;
transform: scale(1.5);
box-shadow: 0 0 5px 2px #fff;
background: black;
}
}

Range Slider styling doesn't work on edge

My CSS style for the range slider doesn't work on Edge. How can I fix the Problem?
I searched on the web for a solution. And added some codes but still not working.
.slider {
-webkit-appearance: none;
width: 100%;
height: 5px;
border-radius: 5px;
background: #d3d3d3;
outline: none;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 15px;
height: 15px;
border-radius: 50%;
background: #33A2D9;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 15px;
height: 15px;
border-radius: 50%;
background: #33A2D9;
cursor: pointer;
}
/*I added this to fix for edge but it doesn't work */
input[type=range]::-ms-thumb{
width: 15px !important;
height: 15px !important;
border-radius: 50% !important;
background: #33A2D9 !important;
cursor: pointer !important;;
}
input[type=range]::-ms-fill-upper {
border-radius: 5px !important;
background: #d3d3d3 !important;
}
input[type=range]::-ms-fill-lower {
border-radius: 5px !important;
background: #d3d3d3 !important;
}
What it should look like (for example on Firefox):
What it look like on edge:
Your "mistake" (if we can call it that) was giving the input a background. You want to give it background-color of transparent and give the -track the desired shade.
Also, as a minor side note and general rule, avoid using background instead of background-color. It is shorter, but it sets a bunch of other background- properties, which you normally don't care about but are a source of common bugs.
Since it tends to be repetitive, I wrote it in SCSS:
$input-height: 16px;
$track-height: 6px;
$thumb-bg: #33A2D9;
$track-bg: #d3d3d3;
#mixin slider-thumb {
width: $input-height;
height: $input-height;
border-radius: $input-height/2;
background-color: $thumb-bg;
appearance: none;
}
#mixin slider-track {
height: $track-height;
border-radius: $track-height/2;
background-color: $track-bg;
appearance: none;
}
.slider[type=range] {
-webkit-transition: .2s;
-webkit-appearance: none;
appearance: none;
width: 100%;
height: $input-height;
background-color: transparent;
outline: none;
opacity: 0.7;
transition: opacity .2s;
cursor: pointer;
&:hover, &:focus, &:active {
opacity: 1;
}
&::-webkit-slider- {
&runnable-track {
-webkit-appearance: none;
#include slider-track;
}
&thumb {
-webkit-appearance: none;
#include slider-thumb;
margin-top: -($input-height - $track-height)/2;
}
}
&::-moz-range- {
&track {
#include slider-track;
}
&thumb {
#include slider-thumb;
margin-top: 0;
}
}
&::-ms- {
&track {
#include slider-track;
}
&fill-upper {
#include slider-track;
}
&fill-lower {
#include slider-track;
}
&thumb {
#include slider-thumb;
margin-top: 0;
}
}
}
Resulting in the following CSS:
.slider[type=range] {
-webkit-appearance: none;
-webkit-transition: .2s;
width: 100%;
height: 16px;
border-radius: 3px;
background-color: transparent;
outline: none;
opacity: 0.7;
transition: opacity .2s;
cursor: pointer;
}
.slider[type=range]:hover, .slider[type=range]:focus, .slider[type=range]:active {
opacity: 1;
}
.slider[type=range]::-webkit-slider-runnable-track {
height: 6px;
border-radius: 3px;
background-color: #d3d3d3;
}
.slider[type=range]::-webkit-slider-thumb {
width: 16px;
height: 16px;
border-radius: 8px;
background-color: #33A2D9;
-webkit-appearance: none;
appearance: none;
margin-top: -5px;
}
.slider[type=range]::-moz-range-track {
height: 6px;
border-radius: 3px;
background-color: #d3d3d3;
}
.slider[type=range]::-moz-range-thumb {
width: 16px;
height: 16px;
border-radius: 8px;
background-color: #33A2D9;
margin-top: 0;
}
.slider[type=range]::-ms-track {
height: 6px;
border-radius: 3px;
background-color: #d3d3d3;
}
.slider[type=range]::-ms-fill-upper {
height: 6px;
border-radius: 3px;
background-color: #d3d3d3;
}
.slider[type=range]::-ms-fill-lower {
height: 6px;
border-radius: 3px;
background-color: #d3d3d3;
}
.slider[type=range]::-ms-thumb {
width: 16px;
height: 16px;
border-radius: 8px;
background-color: #33A2D9;
margin-top: 0;
}
<input type=range class=slider>
Playground here.

The “before” and “after” pseudo-elements are overlapped by wrapper div on the active state

I have created the button which needs border with gradient, in order to do that I have used pseudo-elements "before" and "after"(before with gradient and after with white background color witch overlap before, ordered by z-index). The problem is that when a wrapper div has a background color, the buttons pseudo elements are getting overlapped on the active state! This can be fixed by adding z-index to 0 or 1 to wrapper div... but still, I don't like this workaround! Thanks!
https://jsfiddle.net/x0uw5et3/1/enter code here
Edit wrapper-of-wrapper class to following
.wrapper-of-wrapper {
background-color: purple;
position:relative;
z-index:-2;
}
Hey Here I have your solution your fiddle here
.wrapper-of-wrapper {
background-color: purple;
position: relative;
z-index: 1;
}
body {
background: orange;
}
.wrapper {
/* background-color: orange; */
}
.wrapper-of-wrapper {
background-color: purple;
position: relative;
z-index: 1;
}
.sf-btn {
font-family: Poppins, Helvetica Neue, Helvetica, Arial, sans-serif;
display: inline-block;
margin-bottom: 0;
font-size: 14px;
font-weight: 400;
text-align: center;
white-space: nowrap;
vertical-align: middle;
-ms-touch-action: manipulation;
touch-action: manipulation;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-image: none;
border-radius: 4px;
line-height: 24px;
border: 0;
padding: 8px 16px;
width: 100%;
-webkit-transition: all .4s cubic-bezier(.25, .8, .25, 1);
transition: all .4s cubic-bezier(.25, .8, .25, 1);
-webkit-transition: none;
transition: none;
}
.sf-btn:focus, .sf-btn:hover {
color: #fff;
}
.sf-btn:active, .sf-btn:focus, .sf-btn:hover {
color: #fff;
}
#media (min-width: 640px) {
.sf-btn {
width: auto;
}
}
.sf-btn svg {
fill: inherit;
}
.sf-btn--secondary {
z-index: 3;
color: #262a33;
position: relative;
background-color: #fff;
font-weight: 600;
outline: none;
}
.sf-btn--secondary::before {
background: -webkit-gradient(linear, left top, right top, from(red), color-stop(50%, red), to(#ff7000));
background: linear-gradient(90deg, red, red 50%, #ff7000);
content: "";
position: absolute;
z-index: -2;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 4px;
}
.sf-btn--secondary::after {
content: "";
position: absolute;
background-color: #fff;
border-radius: 4px;
z-index: -1;
top: 2px;
left: 2px;
right: 2px;
bottom: 2px;
}
.sf-btn--secondary:hover {
color: #262a33;
}
.sf-btn--secondary:hover::before {
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
}
.sf-btn--secondary:focus {
color: #262a33;
}
.sf-btn--secondary:focus::before {
z-index: -2;
-webkit-box-shadow: 0 0 6px 2px #ff7000;
box-shadow: 0 0 6px 2px #ff7000;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.sf-btn--secondary:active {
z-index: inherit;
background: linear-gradient(34deg, #eb2506, #eb2506 37%, #ef6f08);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.sf-btn--secondary:active::after {
z-index: -2;
}
.sf-btn--secondary:active::before {
-webkit-box-shadow: none;
box-shadow: none;
}
.sf-btn--lg {
padding: 8px 64px;
font-size: 16px;
line-height: 48px;
font-weight: 700;
}
.sf-btn--full-width {
width: 100%;
margin-right: -4px!important;
}
.sf-btn--full-width::after {
transform: translateX(4px);
}
.wrapper--red {
background-color: red;
z-index: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper-of-wrapper">
<div class="wrapper">
<button class="sf-btn sf-btn--lg sf-btn--secondary">Hello</button>
</div>
</div>

How can I create this button style?

I need to create the button styles in the image below (the one on the right is transparent, not white).
The bottom right corner is obviously the tricky part. It's not just a simple bevel; it's slightly rounded.
The best solution I've come up with is to apply an SVG image mask to a pseudo element positioned to the right of the button and reduce the right padding to compensate. But this approach has its limitations:
it requires a fixed height button (at least, if I want maintain the aspect ratio of the corner)
it requires a different SVG for each button size
I don't see how it can work for the transparent button style
So I'm hoping someone can suggest a different/better approach!
Thanks
UPDATE:
Here is my current approach - https://codepen.io/peteheaney/pen/jwVEPm
$primary: #FAB500;
*, *::after, *::before {
font-family: sans-serif;
box-sizing: border-box;
}
.button {
background-image: none;
border-width: 2px;
border-style: solid;
border-color: transparent;
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-bottom: 0;
text-align: center;
text-decoration: none;
text-transform: uppercase;
touch-action: manipulation;
vertical-align: middle;
white-space: nowrap;
transition: all 0.2s;
&:active,
&:hover,
&:focus {
text-decoration:none;
}
&--large {
font-size: 15px;
padding-left: 24.818px;
height: 52px;
line-height: 52px;
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
position: relative;
margin-right: 24.818px;
&:after {
border-top: 2px solid $primary;
border-bottom: 2px solid $primary;
background: $primary;
content: "";
border-top-right-radius: 6px;
position: absolute;
left: 100%;
bottom: -2px;
width: 24.818px;
height: 52px;
mask: url(http://assets.peteheaney.com.s3.amazonaws.com/button-corner-right.svg) top left / cover;
}
}
&--primary {
color: #000;
background-color: $primary;
border-color: $primary;
&:active,
&:hover,
&:focus {
background-color: darken($primary, 2%);
border-color: darken($primary, 2%);
}
}
}
If you don't mind leaving the corner clickable, you could make the button invisible and just use a background image:
button{
width:x;
height:y;
border:none;
background-color:none
background-image:url(button_image.png);
background-position:center;
background-size:x y;
background-repeat:no-repeat;
}
With button_image.png being the image of your button style without text.
You can try to draw it like this using before and after :
.button {
position: relative;
display: inline-block;
background-color: orange;
color: white;
padding: 20px 40px;
font-size: 14px;
border-radius: 5px;
text-decoration: none;
}
.button:after {
content: '';
position: absolute;
z-index: 10;
display: block;
bottom: -6px;
right: -2px;
width: 10px;
height: 20px;
transform: rotate(45deg);
background-color: white;
}
.button:before {
content: '';
position: absolute;
z-index: 100;
display: block;
bottom: -1px;
right: 4px;
width: 13px;
height: 23px;
transform: rotate(45deg);
background-color: orange;
border-radius: 10px;
}
Button
Here is an example of how this could possibly be achieved with pure CSS.
However an image or an SVG might be a more efficient way to solve this issue.
.Large{
position:relative;
display:inline-block;
background:#FFB300;
border:none;
padding:20px 0 20px 30px;
border-radius:10px 0 0 10px;
height:40px;
font:700 1.5em/40px Arial;
}
.Large::after{
content:"";
display:block;
position:absolute;
top:0;
right:-30px;
width:30px;
height:50px;
background:#FFB300;
border-radius:0 10px 0 0;
}
.Large::before{
content:"";
display:block;
position:absolute;
bottom:0;
right:-30px;
width:0;
height:0;
border-top: 15px solid #FFB300;
border-right: 15px solid transparent;
border-bottom: 15px solid transparent;
border-left: 15px solid #FFB300;
}
<a class="Large">LARGE</a>
I am not really happy with my result, but here it goes just in case you can make it better.
The different color is just to make it easier to see what is what.
I have focused on solving the transparent one. Once you have it, solving the other is easier.
:root {
--width: 10px;
--width2: 14px;
}
.test {
position: relative;
margin: 20px;
width: 300px;
height: 150px;
position: absolute;
border: var(--width) solid transparent;
border-image: linear-gradient(to bottom right, orange 0%, orange 70%, transparent 70%);
border-image-slice: 1;
}
.test:before {
content: "";
position: absolute;
height: 25px;
width: 150px;
right: 29px;
bottom: -10px;
transform: skewX(-45deg);
border: solid 0px transparent;
border-bottom-color: red;
border-bottom-width: var(--width);
border-right-color: red;
border-right-width: var(--width2);
border-bottom-right-radius: 25px;
}
.test:after {
content: "";
position: absolute;
height: 50px;
width: 25px;
right: -10px;
bottom: 29px;
transform: skewY(-45deg);
border: solid 0px transparent;
border-bottom-color: red;
border-bottom-width: var(--width2);
border-right-color: red;
border-right-width: var(--width);
border-bottom-right-radius: 25px;
}
<div class="test"></div>
I decided to go for the approach I have demonstrated in this pen - https://codepen.io/peteheaney/pen/bRBOMq (compiled CSS version below)
*, *::after, *::before {
font-family: sans-serif;
box-sizing: border-box;
}
.button {
background-image: none;
border-style: solid;
border-top-width: 2px;
border-bottom-width: 2px;
border-left-width: 2px;
border-right-width: 0;
border-color: transparent;
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-bottom: 0;
text-align: center;
text-decoration: none;
text-transform: uppercase;
touch-action: manipulation;
vertical-align: middle;
white-space: normal;
transition: all 0.2s;
}
.button:active, .button:hover, .button:focus {
text-decoration: none;
}
.button--large {
font-size: 15px;
padding: 16px 0 14px 21px;
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
position: relative;
margin-right: 21px;
}
.button--large:before {
content: "";
position: absolute;
left: 100%;
top: -2px;
width: 21px;
height: calc(100% - 17px);
border-top-right-radius: 6px;
}
.button--large:after {
position: absolute;
left: 100%;
bottom: -2px;
width: 21px;
height: 21px;
transition: all 0.2s;
}
.button--primary {
color: #000;
background-color: #FAB500;
border-color: #FAB500;
}
.button--primary:before {
background-color: #FAB500;
transition: all 0.2s;
}
.button--primary:active:before, .button--primary:hover:before, .button--primary:focus:before {
background-color: #f0ae00;
border-color: #f0ae00;
}
.button--primary:after {
content: url(http://assets.peteheaney.com.s3.amazonaws.com/button-corner-primary-large.svg);
}
.button--primary:active, .button--primary:hover, .button--primary:focus {
background-color: #f0ae00;
border-color: #f0ae00;
}
.button--secondary {
color: #000;
border-color: #FAB500;
}
.button--secondary:before {
border: 2px solid #FAB500;
border-bottom: 0;
border-left: 0;
transition: all 0.2s;
}
.button--secondary:active:before, .button--secondary:hover:before, .button--secondary:focus:before {
background-color: #FAB500;
}
.button--secondary:after {
content: url(http://assets.peteheaney.com.s3.amazonaws.com/button-corner-secondary-large.svg);
}
.button--secondary:active, .button--secondary:hover, .button--secondary:focus {
background-color: #FAB500;
border-color: #FAB500;
}
<a class="button button--large button--primary" href="">My button</a>
<a class="button button--large button--secondary" href="">My other button</a>
Firstly, I divided the right-hand portion into top and bottom (using :before and :after). The top-right pseudo element just has a background color and a top right border radius. This way the top-right portion can have a flexible height, meaning the buttons don't need to have a fixed height. The bottom right pseudo element is essentially an SVG ( using content: url(/path/to/svg.svg) ). This pseudo element always has a fixed width and height, so it maintains its size and aspect ratio regardless of the width/height of the button.
The outline style button is just a variation on the other style, with more borders and less backgrounds.
The only downside to this approach is the need for a different SVG for each button style. But I'm happy with that compromise.
Another take on Arthur's approach.
If you create the bottom right image (the white corner and the yellow corner border) you are able to position this so it stays to the bottom right and you have the rest of the button to style yourself.
button {
background-image:url(corner.svg);
height: 20px;
padding: 5px;
border-radius: 5px;
background-color: yellow;
background-repeat: no-repeat;
background-position: bottom right;
}

Spaceship menu with CSS

Basically, the image below summarizes my question.
Is there any elegant solution to make it work? I've tried to use rotate, skew and perspective, but didn't work for me.
Note: the background needs to be transparent.
My code for you. :)
* { box-sizing: border-box; }
body { font: normal 16px sans-serif; }
.spaceship {
height: 430px;
position: relative;
width: 140px;
}
.spaceship::before {
background: #006dd9;
border-radius: 100%;
content: '';
height: 70px;
position: absolute;
width: 140px;
z-index: 1;
}
.abduction {
background: #0f0;
height: 370px;
left: 20px;
padding-top: 10px;
position: absolute;
top: 60px;
width: 100px;
}
.abduction a {
color: #fff;
display: block;
height: 60px;
padding-top: 25px;
text-align: center;
text-decoration: none;
text-transform: uppercase;
transition: background 500ms;
}
.abduction a:nth-child(even) { background: #00d900; }
.abduction a:hover { background: #008c00; }
<div class="spaceship">
<div class="abduction">
Button 1
Button 2
Button 3
Button 4
Button 5
Button 6
</div>
</div>
Here's what I changed your css to make it look like your picture and do the correct hover effect:
* { box-sizing: border-box; }
body { font: normal 16px sans-serif; }
.spaceship {
height: 430px;
position: relative;
width: 140px;
}
.spaceship::before {
background: #006dd9;
border-radius: 100%;
content: '';
height: 70px;
position: absolute;
width: 140px;
z-index: 1;
}
.abduction {
height: 370px;
left: 20px;
padding-top: 5px;
position: absolute;
top: 60px;
width: 100px;
}
.abduction a {
color: #fff;
display: block;
height: 65px;
margin: 0 auto;
padding: 0;
border-bottom: 65px solid #0f0;
border-left: 3px solid transparent;
border-right: 3px solid transparent;
line-height: 5;
font-size: 12px;
text-align: center;
text-decoration: none;
text-transform: uppercase;
transition: border-bottom-color 500ms;
}
.abduction a:nth-child(5){
width: 94px;
}
.abduction a:nth-child(4){
width: 88px;
}
.abduction a:nth-child(3){
width: 82px;
}
.abduction a:nth-child(2){
width: 76px;
}
.abduction a:nth-child(1){
width: 70px;
}
.abduction a:nth-child(even) { border-bottom-color: #00d900; }
.abduction a:hover { border-bottom-color: #008c00; }
<div class="spaceship">
<div class="abduction">
Button 1
Button 2
Button 3
Button 4
Button 5
Button 6
</div>
</div>
So basically to create a 65px high trapezoid with borders (colored #0f0) you'd do this:
border-bottom: 65px solid #0f0;
border-left: 3px solid transparent;
border-right: 3px solid transparent;
The width of the last element is 100px. So since the left border width + the right border width = 6px and 100px - 6px = 94px, the second to last element will have a width of 94px to match the top of the last element. You subtract the side border sum from the previous elements width to get the current element width.
Also the transition property needs to be changed to border-bottom-color instead of background because border-bottom-color is what sets the color of the trapezoid.
* { box-sizing: border-box; }
body { font: normal 16px sans-serif; }
.spaceship {
height: 430px;
position: relative;
width: 140px;
}
.spaceship::before {
background: #006dd9;
border-radius: 100%;
content: '';
height: 70px;
position: absolute;
width: 140px;
z-index: 1;
}
.abduction {
height: 370px;
left: 15px;
padding-top: 10px;
position: absolute;
top: 50px;
width: 110px;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 400px solid #0f0;
}
.abduction a {
color: #fff;
display: block;
height: 60px;
padding-top: 25px;
text-align: center;
text-decoration: none;
text-transform: uppercase;
transition: background 500ms;
}
.abduction a:nth-child(even) { background: #00d900; }
.abduction a:hover { background: #008c00; }
<div class="spaceship">
<div class="abduction">
Button 1
Button 2
Button 3
Button 4
Button 5
Button 6
</div>
</div>
I'm pretty sure you need javascript for that.
jQuery(document).ready(function(){
var buttons = [{name:'button'},{name:'button'},{name:'button'},{name:'button'},{name:'button'},{name:'button'}];
var b;
for(b in buttons){
var rev = buttons.length - (b*10);
var btn = jQuery(''+ buttons[b].name + ' ' + b +'').css({left:rev/2, width:100 - rev} );
jQuery('.abduction').append(btn);
}
});
* { box-sizing: border-box; }
body { font: normal 16px sans-serif; }
.spaceship {
height: 430px;
position: relative;
width: 140px;
}
.spaceship::before {
background: #006dd9;
border-radius: 100%;
content: '';
height: 70px;
position: absolute;
width: 140px;
z-index: 1;
}
.abduction {
height: 370px;
left: 20px;
padding-top: 10px;
position: absolute;
top: 60px;
width: 100px;
}
.abduction a {
display:block;
position:relative;
color: #fff;
display: block;
height: 60px;
text-align: center;
text-decoration: none;
text-transform: uppercase;
transition: background 500ms;
border-bottom:80px solid #0f0;
border-left:5px solid transparent;
border-right:5px solid transparent;
}
.abduction a:nth-child(even) { border-bottom: 80px solid #00d900; }
.abduction a:hover { border-bottom: 80px solid #008c00; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="spaceship">
<div class="abduction">
</div>
</div>

Resources