How I made an iPhone 4 in CSS3
Jan 26, 2012     16:30:00

In 19th December 2011 I published my creation, iPhone4 in CSS3, to my website. Since that time more then 400 000 unique visitors saw it, many of them like and share it. And now i want to tell how I made it from the stage of beginning to the first tweet about it's finished.


The main idea of this iPhone was a challenge. One of my coworkers give mi a link with iOS Icons made in Pure CSS and after I saw what was there I decided to create something cool like that or even cooler. My brain decide - "Challenge excepted!". And it was the beginning.

Main task

That day was born an idea to create not only icons, but whole iPhone in CSS3 (with no images, SVG, base64, canvas at all) and give a life to it with some interaction:

  • turning on and off like in a real iPhone;
  • working "Slide to unlock" slider;
  • close to real "slide to unlock" animation;



Main interesting CSS3 properties that helps me to paint (to design) the iPhone:

  • border-radius for rounding corners of almost all elements;
  • box-shadow for creating shadows and inner glows;
  • background-size for creating ribbed background in 'Message' and 'Phone' icons;
  • transform (rotate, skew, scale) - transforming some parts of icons, it helps to create icon details close to real pictures;
  • ::before and ::after elements helps minimize HTML code elements;
  • :nth-child(n) helps to chose needed elements from the array;

jQuery + jQuery UI

From this technology I was using not to much interesting things. animate() function to create "slide to unlock" animation, for flying in and out icons when unblocking or blocking the device. draddable() + animate() function to enable finger dragging the slider.

Script style inherited from Html5BoilerPlate.


Html structure is very simple. I was not using many different tags. The main of them are 'div', 'hr', 'b' and lists. Everything important has been assigned to CSS3.

Parts of code

HTML structure of the iPhone

<div class="iphone">

     <div class="iphone_light_gradient"></div> <!-- glare on the iPhone -->
     <div class="iphone_power_button" id="iphone_power_button"></div> <!-- on/off button -->
     <div class="iphone_voice_toogle"></div> <!-- voice toogle -->
     <div class="iphone_voice_plus"></div> <!-- button "+" -->
     <div class="iphone_voice_minus"></div> <!-- button "-" -->

     <div class="iphone_camera"></div> <!-- camera -->

     <div class="iphone_dynamic"><span></span><!-- lots of 'span' for dynamic --><span></span></div> <!-- dynamic -->
     <div class="iphone_black_bg"></div> <!-- black background of front part of iPhone -->

     <div class="iphone_display" > <!-- display -->

          <div class="iphone_headline" id="iphone_headline"> <!-- top dark line -->
               <div class="iphone_net"></div> <!-- operator network -->
               <div class="iphone_net_title">tjrus</div> <!-- name of the phone network -->
               <div class="iphone_wi-fi"><div class="hack"></div></div> <!-- wi-fi indocator -->
               <div class="iphone_clock" id="iphone_headline_clock">00:00</div> <!-- clock -->
               <div class="iphone_lock"></div> <!-- lock -->
               <div class="iphone_battery"></div> <!-- battery -->
          <div class="iphone_header" id="iphone_lock_header"> <!-- top panel of lock screen -->
               <div class="iphone_time" id="iphone_lock_time">0<span>:</span>00</div> <!-- clock -->
               <div class="iphone_date" id="iphone_lock_date"></div> <!-- date -->
          <div class="iphone_footer" id="iphone_lock_footer"> <!-- bottom part of lock panel -->
               <div class="iphone_unlock" id="iphone_unlock"> <!-- "slide to unlock" -->
                    <div class="iphone_slider" id="iphone_slider"></div> <!-- slider -->
                    <div class="iphone_slide2unlock" id="iphone_slide2unlock">slide to unlock</div> 
          <div class="iphone_icons_containter" id="iphone_icons_containter"> <!-- icons container -->
               <div class="icon"></div> <!-- example of icon container (there are 16 icons here) -->
          <div class="iphone_dock" id="iphone_dock"> <!-- dock -->
               <div class="icon"></div> <!-- example of icon container (there are 4 icons here) -->

     <div class="iphone_home" id="iphone_home_button"></div> <!-- home button -->


CSS3 interesting parts

There is no sense to give you full CSS3 code in 3395 lines. So here is interesting parts.


All icons are in container with .icon class. So I can easily change their order or simply delete some of them. And also can easily give them general style.

.icon {
     width: 56px;
     height: 56px;
     border-radius: 10px;
     box-shadow: rgba(0,0,0,0.5) 0 1px 2px;
     margin-bottom: 30px;
     position: absolute;

.icon span { /* contains icon title */
     display: block;
     text-align: center;
     font: bold 11px/15px "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
     color: #fff;
     text-shadow: rgba(0,0,0,0.3) 1px 2px 1px;
     text-transform: capitalize;
     position: absolute;
     top: 58px;
     left: -10px;
     width: 76px;

We have the array or icons, so the insist way i find to put them on their places is:

.icon:nth-child(4n + 1) { left:17px; }
.icon:nth-child(4n + 2) { left:92px; }
.icon:nth-child(4n + 3) { left:168px; }
.icon:nth-child(4n + 4) { left:243px; }

.icon:nth-child(-n + 16) { top: 258px; }
.icon:nth-child(-n + 12) { top: 172px; }
.icon:nth-child(-n + 8) { top: 86px; }
.icon:nth-child(-n + 4) { top: 0; }

in case of dock icons we have a little different situation:

.iphone_dock .icon:nth-child(1) { margin-left:7px; margin-right: 19px; }
.iphone_dock .icon:nth-child(2) { margin-right: 20px; }
.iphone_dock .icon:nth-child(3) { margin-right: 19px; }

If you are interested in full icons code you can find it in main styles of that project

jQuery interesting parts

As I already told I inherit script style from Html5BoilerPlate. All options, possibilities and sattes of the iPhone a structured in one object:

iphone = {
     slide_started          : false, // is slide started
     letter_animate_time    : 50, // time of letter animation
     panels_animate_time    : 400, // panels animation time
     status                 : 'lock', // Current iPhone status. available statuses: "lock", "unlock", "off"
     iconsDefaultPosition   : {}, // default icon positions
     iconsOutPosition       : {}, // icons out positions

     init : function(){}, // initialize all functionality

     endSlide : function(){}, // function that processes the end of slide action

     turnOn : function(){}, // turning iPhone on
     turnOff : function(){}, // turning iPhone off
     lock : function(){}, // locking iPhone
     unlock : function(){}, // unlocking iPhone

     showIcons : function(){}, // icons incoming animation

     hideIcons : function(){}, // icons hiding

     animateHideIcons : function(){}, // animated icons hiding

     prepareIcons : function(){}, // gethering default icons position

     timeUpdate : function(){}, // updating time on clocks
     stopTextAnimate : function(){}, // stops the text animation
     startTextAnimate : function(){}, // starting text animation
     prepareTextAnimate : function () {}, // prepating "slide to unlock" for animation
     animateLetters : function() {}, // start of animation cycle in "slide to unlock"

     ua : function() {}, // user agent identification

Treatment "slide to unlock" process
     containment: 'parent',
     axis: 'x',
     start: function(event, ui) {
                    var left = $("#iphone_slider").css('left').substring(0, $("#iphone_slider").css('left').length - 2);
                    var width = $('#iphone_unlock').width() - $('#iphone_slider').width();
                    var opacity_k = (width - left*3) / (width);
                    $('#iphone_slide2unlock').css({'opacity': opacity_k}, TIME/2); // controls the text opacity while sliding
     stop: function(event, ui){
     iphone.slide_started = true;
     if (iphone.slide_started){
          iphone.endSlide(); // here we find out how far users slide the slider to unlock iPhone or return to starting position
          iphone.slide_started = false;

The result

The result page shows the many excellent, but not all CSS3 possibilities. It a pity but all this code can't be used on websites because of the huge complex of CSS3 properties slows browser too much.

Cross-browser compatibility

This is the most sad point:). The iPhone 4 in CSS3 working great in latest Webkit browsers (Safari and Chrome) under MacOS X (in Windows family there is a trouble with 'Phone' icon), also in latest Firefox and Opera browsers.

For iOS devices the animation of 'slide to unlock' letters was disabled due to the fact that this strongly slow down the browser.


The main page - iPhone 4 in CSS3

styles — iphone.css

script — iphone.js

blog comments powered by Disqus