…just another arrow button in pure CSS…
arrow button in pure CSS and HTML – iOS 6 version
DemoSome of you might have already seen or used my first version of an iOS arrow button in pure CSS.
I noticed that in iOS 6 the look of these buttons changed. For example the gradient. It is no longer split in the middle. I remember this being one of the main problems when I did the iOS 5 arrow button in pure CSS.
But not only that was the problem. It was more or less a dirty -webkit- hack which evolved to some kind of cross-browser arrow button in pure CSS. I was never really happy with the very first version, so I made a second one right after which looked pretty original.
Now 1 1/2 years later having done a lot more crazy CSS UI elements I guess I can achieve a lot better result.. well I sure hope I can ;).
This works in Chrome, Safari, Firefox 3.6+, Opera, IE10, (IE9 almost)
@import "compass/css3";
@import "compass/support";
$experimental-support-for-svg: true;
@mixin ios6-arrow-button ($theme: none){
$button-color-bottom: #41618d;
$button-color-top: #99aac2;
$button-border-color-bottom: lighten($button-color-bottom, 20%);
$button-text-shadow: 0 -1px 0 #474747;
$button-text-color: #fff;
@if $theme == light {
$button-color-bottom: #cccccc;
$button-color-top: #d4d7d4;
$button-border-color-bottom: darken($button-color-bottom, 5%);
$button-text-shadow: 0 1px 0 #fff;
$button-text-color: #474747;
} @else if $theme == dark {
$button-color-bottom: #111;
$button-color-top: #444;
$button-border-color-bottom: lighten($button-color-bottom, 60%);
$button-text-shadow: 0 -1px 0 #000;
$button-text-color: #fff;
}
@include appearance(none);
@include inline-block;
position: relative;
overflow: visible;
margin: 0;
padding: 0;
min-width: 20px;
height: 26px;
border: 0;
background: none;
cursor: pointer;
&.left {
&:before {
@include box-sizing( border-box);
@include box-shadow(1px 2px 1px -2px rgba(0,0,0,0.4) inset, -1px 4px 2px -4px rgba(0,0,0,0.4) inset);
@include background-image(linear-gradient(top right, $button-color-top, $button-color-bottom));
@include background-size( 20px 18px);
@include transform(rotate(-45deg) scale(0.86) skew(-9deg, -9deg));
@include transform-origin(50%);
@include inline-block;
@include border-radius(0 6px 0 6px);
@include border-top-right-radius(8px 5px);
@include border-bottom-left-radius(5px 8px);
position: relative;
top: 0;
left: 16px;
width: 22px;
height: 22px;
content: "";
border: {
width: 0 0 1px 1px;
color: transparent transparent transparent $button-border-color-bottom;
style: solid;
}
background: {
position: -2px 0;
repeat: no-repeat;
}
}
&:after {
@include box-sizing(border-box);
@include background-image(linear-gradient(top, $button-color-top, $button-color-bottom));
@include background-size(26px 26px);
@include box-shadow(0 2px 2px -2px rgba(0,0,0,0.4) inset, -1px 1px 1px -1px rgba(0,0,0,0.4) inset);
@include text-shadow($button-text-shadow);
@include inline-block;
@include border-radius(4px);
position: relative;
top: 0;
left: 2px;
margin: 0;
padding: 5px 10px 5px 5px;
width: auto;
height: 26px;
color: $button-text-color;
content: attr(data-title);
text-decoration: none;
white-space: nowrap;
line-height: 16px;
border: {
width: 0 0 1px 0;
color: $button-border-color-bottom;
style: solid;
}
font: {
weight: 500;
size: 12px;
family: "HelveticaNeue-Bold", "Helvetica Neue Bold", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
}
}
}
&:hover:after {
@include background-image(linear-gradient(top, darken($button-color-bottom, 20%), darken($button-color-top, 5%)));
@include background-size(26px 26px);
}
&:hover:before {
@include background-image(linear-gradient(top right, darken($button-color-bottom, 20%), darken($button-color-top, 5%)));
@include background-size( 20px 18px);
}
}
.ios-6-arrow.blue {
@include ios6-arrow-button();
}
.ios-6-arrow.light {
@include ios6-arrow-button(light);
}
.ios-6-arrow.dark {
@include ios6-arrow-button(dark);
}
Check out this Pen!
First things first – the markup
We need a simple button:
<button>Back</button>
… but let’s add some attributes class="ios-6-arrow left blue" data-title="Back"
, which are needed to make a flexible arrow button.
<button class="ios-6-arrow left blue" data-title="Back"></button>
…notice that I moved the text to a data-attribute, so the button itself does not contain text anymore.
The styling – pure CSS
Step one: create the bottom layer
Most of this layer will be hidden in the next steps, so it will not be visible at all.
.ios-6-arrow.blue { display: -moz-inline-stack; display: inline-block; vertical-align: middle; *vertical-align: auto; zoom: 1; *display: inline; -webkit-appearance: none; -moz-appearance: none; appearance: none; background: none; position: relative; margin: 0; padding: 0; border: 0; height: 26px; min-width: 20px; cursor: pointer; overflow: visible; }
Step two: create the tip
In this step we will create the tip for the button.
I took me a little to get a decent overlap. Note that this does not include an image-mask like my first version, but rather focuses on the cross-browser thought like my cross-browser-hack from version 1. Notice that the button does not have any text yet, it will be added by another pseudo-element
in the next step.
.ios-6-arrow.blue.left:before { -webkit-box-shadow: 1px 2px 1px -2px rgba(0, 0, 0, 0.4) inset, -1px 4px 2px -4px rgba(0, 0, 0, 0.4) inset; -moz-box-shadow: 1px 2px 1px -2px rgba(0, 0, 0, 0.4) inset, -1px 4px 2px -4px rgba(0, 0, 0, 0.4) inset; box-shadow: 1px 2px 1px -2px rgba(0, 0, 0, 0.4) inset, -1px 4px 2px -4px rgba(0, 0, 0, 0.4) inset; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjEwMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzk5YWFjMiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzQxNjE4ZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background-image: -webkit-gradient(linear, 100% 0%, 0% 100%, color-stop(0%, #99aac2), color-stop(100%, #41618d)); background-image: -webkit-linear-gradient(top right, #99aac2, #41618d); background-image: -moz-linear-gradient(top right, #99aac2, #41618d); background-image: -o-linear-gradient(top right, #99aac2, #41618d); background-image: linear-gradient(top right, #99aac2, #41618d); -webkit-background-size: 20px 18px; -moz-background-size: 20px 18px; -o-background-size: 20px 18px; background-size: 20px 18px; -webkit-transform: rotate(-45deg) scale(0.86) skew(-9deg, -9deg); -moz-transform: rotate(-45deg) scale(0.86) skew(-9deg, -9deg); -ms-transform: rotate(-45deg) scale(0.86) skew(-9deg, -9deg); -o-transform: rotate(-45deg) scale(0.86) skew(-9deg, -9deg); transform: rotate(-45deg) scale(0.86) skew(-9deg, -9deg); -webkit-transform-origin: 50% 50%; -moz-transform-origin: 50% 50%; -ms-transform-origin: 50% 50%; -o-transform-origin: 50% 50%; transform-origin: 50% 50%; position: relative; display: -moz-inline-stack; display: inline-block; vertical-align: middle; *vertical-align: auto; zoom: 1; *display: inline; top: 0; left: 16px; width: 22px; height: 22px; border: 1px solid #f00; border-width: 1px; border-width: 0 0 1px 1px; border-color: #7594bf transparent transparent #7594bf; background-position: -2px 0; background-repeat: no-repeat; content: ""; -webkit-border-radius: 0 6px 0 6px; -moz-border-radius: 0 6px 0 6px; -ms-border-radius: 0 6px 0 6px; -o-border-radius: 0 6px 0 6px; border-radius: 0 6px 0 6px; -moz-border-radius-topright: 8px 5px; -webkit-border-top-right-radius: 8px 5px; border-top-right-radius: 8px 5px; -moz-border-radius-bottomleft: 5px 8px; -webkit-border-bottom-left-radius: 5px 8px; border-bottom-left-radius: 5px 8px; }
Step three: create the top layer
So, in this step we will finally add the text to the button.
The content is taken from a data-attribute
, in this case data-title
.
.ios-6-arrow.blue.left:after { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-border-radius: 4px 4px 4px 4px; -moz-border-radius: 4px 4px 4px 4px; -ms-border-radius: 4px 4px 4px 4px; -o-border-radius: 4px 4px 4px 4px; border-radius: 4px 4px 4px 4px; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjAlIiB4Mj0iNTAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzk5YWFjMiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzQxNjE4ZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #99aac2), color-stop(100%, #41618d)); background-image: -webkit-linear-gradient(top, #99aac2, #41618d); background-image: -moz-linear-gradient(top, #99aac2, #41618d); background-image: -o-linear-gradient(top, #99aac2, #41618d); background-image: linear-gradient(top, #99aac2, #41618d); -webkit-background-size: 26px 26px; -moz-background-size: 26px 26px; -o-background-size: 26px 26px; background-size: 26px 26px; -webkit-box-shadow: 0 2px 2px -2px rgba(0, 0, 0, 0.4) inset, -1px 1px 1px -1px rgba(0, 0, 0, 0.4) inset; -moz-box-shadow: 0 2px 2px -2px rgba(0, 0, 0, 0.4) inset, -1px 1px 1px -1px rgba(0, 0, 0, 0.4) inset; box-shadow: 0 2px 2px -2px rgba(0, 0, 0, 0.4) inset, -1px 1px 1px -1px rgba(0, 0, 0, 0.4) inset; text-shadow: 0 -1px 0 #474747; position: relative; top: 0; left: 2px; display: -moz-inline-stack; display: inline-block; vertical-align: middle; *vertical-align: auto; zoom: 1; *display: inline; padding: 5px 10px 5px 5px; margin: 0; width: auto; height: 26px; border: 1px solid #7594bf; border-width: 0 0 1px 0; content: attr(data-title); text-decoration: none; white-space: nowrap; font-weight: 500; color: white; font-size: 12px; font-family: "HelveticaNeue-Bold", "Helvetica Neue Bold", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 16px; }
hover styles
.ios-6-arrow.blue:hover:after { background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjAlIiB4Mj0iNTAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzIxMzE0NyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzg5OWRiOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #213147), color-stop(100%, #899db8)); background-image: -webkit-linear-gradient(top, #213147, #899db8); background-image: -moz-linear-gradient(top, #213147, #899db8); background-image: -o-linear-gradient(top, #213147, #899db8); background-image: linear-gradient(top, #213147, #899db8); -webkit-background-size: 26px 26px; -moz-background-size: 26px 26px; -o-background-size: 26px 26px; background-size: 26px 26px; } .ios-6-arrow.blue:hover:before { background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjEwMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzIxMzE0NyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzg5OWRiOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background-image: -webkit-gradient(linear, 100% 0%, 0% 100%, color-stop(0%, #213147), color-stop(100%, #899db8)); background-image: -webkit-linear-gradient(top right, #213147, #899db8); background-image: -moz-linear-gradient(top right, #213147, #899db8); background-image: -o-linear-gradient(top right, #213147, #899db8); background-image: linear-gradient(top right, #213147, #899db8); -webkit-background-size: 20px 18px; -moz-background-size: 20px 18px; -o-background-size: 20px 18px; background-size: 20px 18px; }
Writing a SASS mixin
Well, of course this looks like a lot of code for a simple button…
nobody wants to write code like that…
To make things easier and to make sure this button is as compatible as possible, we will use SASS with “Compass“. Any web-developer who isn’t using these or another preprocessor should definitely take a look at one, they can make your life a lot easier when your styling relies on vendor-prefixed properties.
So for this project I want to create a mixin so I can easily make new button-styles.
@import "compass/css3"; @import "compass/support"; $experimental-support-for-svg: true; @mixin ios6-arrow-button ($theme: none){ $button-color-bottom: #41618d; $button-color-top: #99aac2; $button-border-color-bottom: lighten($button-color-bottom, 20%); $button-text-shadow: 0 -1px 0 #474747; $button-text-color: #fff; @if $theme == light { $button-color-bottom: #cccccc; $button-color-top: #d4d7d4; $button-border-color-bottom: darken($button-color-bottom, 5%); $button-text-shadow: 0 1px 0 #fff; $button-text-color: #474747; } @else if $theme == dark { $button-color-bottom: #111; $button-color-top: #444; $button-border-color-bottom: lighten($button-color-bottom, 60%); $button-text-shadow: 0 -1px 0 #000; $button-text-color: #fff; } @include inline-block; @include appearance(none); background: none; position: relative; margin: 0; padding: 0; border: 0; height: 26px; min-width: 20px; cursor: pointer; overflow: visible; &.left { &:before { @include box-shadow(1px 2px 1px -2px rgba(0,0,0,0.4) inset, -1px 4px 2px -4px rgba(0,0,0,0.4) inset); @include box-sizing( border-box); @include background-image(linear-gradient(top right, $button-color-top, $button-color-bottom)); @include background-size( 20px 18px); @include transform(rotate(-45deg) scale(0.86) skew(-9deg, -9deg)); @include transform-origin(50%); position: relative; @include inline-block; top: 0; left: 16px; width: 22px; height: 22px; border: 1px solid #f00; border-width: 1px; border-width: 0 0 1px 1px; border-color: $button-border-color-bottom transparent transparent $button-border-color-bottom; background-position: -2px 0; background-repeat: no-repeat; content: ""; @include border-radius(0 6px 0 6px); @include border-top-right-radius(8px 5px); @include border-bottom-left-radius(5px 8px); } &:after { @include box-sizing(border-box); @include border-radius(4px 4px 4px 4px); @include background-image(linear-gradient(top, $button-color-top, $button-color-bottom)); @include background-size(26px 26px); @include box-shadow(0 2px 2px -2px rgba(0,0,0,0.4) inset, -1px 1px 1px -1px rgba(0,0,0,0.4) inset); @include text-shadow($button-text-shadow); position: relative; top: 0; left: 2px; @include inline-block; padding: 5px 10px 5px 5px; margin: 0; width: auto; height: 26px; border: 1px solid $button-border-color-bottom; border-width: 0 0 1px 0; content: attr(data-title); text-decoration: none; white-space: nowrap; font-weight: 500; color: $button-text-color; font-size: 12px; font-family: "HelveticaNeue-Bold", "Helvetica Neue Bold", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 16px; } } &:hover:after { @include background-image(linear-gradient(top, darken($button-color-bottom, 20%), darken($button-color-top, 5%))); @include background-size(26px 26px); } &:hover:before { @include background-image(linear-gradient(top right, darken($button-color-bottom, 20%), darken($button-color-top, 5%))); @include background-size( 20px 18px); } }
So now we can just include the mixin for our arrow button
.ios-6-arrow.blue { @include ios6-arrow-button(); } .ios-6-arrow.light { @include ios6-arrow-button(light); } .ios-6-arrow.dark { @include ios6-arrow-button(dark); }
This works in Chrome, Safari, Firefox 3.6+, Opera, IE10, (IE9 almost)
Here’s a screenshot from IE9. Sadly the SVG renders incorretly.. but hey …for IE9 it’s quite OK isn’t it?
Well, for compatibility it is better to remove the experimental svg support and just use plain colors instead. This way it actually looks pretty decent on IE9
SVG support:
Plain color
Creating an iOS 5 Style arrow button with this technique
Of course we can also create the iOS 5 arrow button style with this technique.
Here’s an example:
Gregor Adams
I specialize in CSS, HTML and JavaScript. As I am a huge fan and also a student of open-source, I try to help other programmers (especially newcomers) as much as I can. I am also very happy for "true" criticism. So feel free to ask any question you like and I will try to give the best possible answer.
Pingback: the best pure CSS3 iOS style arrow "Back" button | CSS3, tutorials()
Pingback: arrow button in pure CSS & HTML : ちゅどん道中記()