Implementation: UI: A scalable phone

Jérôme Beau
4 min readJul 2, 2024

--

This article was originally published on CodePen October 21th, 2017.

In this a tutorial to show how to emulate a phone sliding in a pure CSS way. You may often see such phone sliders, but most of them use fixed pixel sizes. Here our goal is to produce an animated phone that can have any size.

In 2017, iPhones had a physical button ;)

We will learn to:

  • position elements one over another (in a proportional/fluid way, so that the result is resizeable) ;
  • hide parts of elements ;
  • animate elements.

We’ll dot it with a pure CSS approach, emphasizing that we should always leverage the existing styling engine first, before adding Javascript code.

The structure

Your HTML structure should be as semantic as possible. In our example, we want to emulate a phone, and all we have to do is to describe the phone structure : the hardware part (a phone that contains a screen) as well as the software part (a sliding zone that contains images), as we want to represent both :

<div class="phone">
<div class="screen">
<div class="slide">
<img src="img1">
<img src="img2">
</div>
</div>
</div>

Skinning a rectangle

Now we have to provide some skin on those blocks. For the sake of simplicity, we’ll provide the phone skin through an iPhone image. But where could we put it? There are two options:

  • Set a background image on the phone block. This is tempting at first thought, but will prove hazardous : the background image can either be set to cover the phone space, thus leaving a part hidden on such a rectangular block, or to be contained in it, thus leaving some empty space in it for the same reasons. In summary, this would prevent us to position the screen precisely over the phone image only.
  • Position an image over the phoneblock precisely, i.e. absolutely.

So we will opt in for the latter option, and add an iPhone to fill the phone block:

<div class="phone">
<img src="iPhoneImage.png">
<div class="screen">
<div class="slide">
<img src="img1">
<img src="img2">
</div>
</div>
</div>

Of course we want this image to fill up the whole phone block:

.phone {
img {
width: 100%;
height: 100%;
}
}

Positionning elements

Now we have to position the screen block over the phone block. As we want the final result to adapt its size to its container, we'll use percentage units, relative to their containers. Expressed this way, the screen is:

  • 15% from the top of the phone ;
  • 6% of its left edge ;
  • 70% of its height, and
  • 88% of its width.

which translates in CSS:

.screen {
position: absolute;
top: 15%;
left: 6%;
height: 70%;
width: 88%;
}

The sliding part

We have described the slide block as being inside the screen but, by its nature, the size of this "software" part goes beyond the width of its container. In our example, it actually take two times the width of the screen, since we want to display (through sliding) two home screens. Eventually, since the slider will be wider than the screen, we have to tell that screen not to display contents wider than its own width. We express this this way:

.screen {
.slide {
position: absolute;
left: 0;
width: 200%;
height: 100%;
}
overflow: hidden;
}

The slided contents

Now all we have to do is to require that the home screens images display side by side (i.e. float on the left side of one another). And we have to tell which size those home screens will have relatively to their container’s size. Since the containing slider is sized to host two slides, each home screen image will take half of the slider’s width:

.slide {
img {
float:left;
width:50%;
height:100%;
}
}

Animating it

Now your sliding phone is operational. You can play with the left CSS property value (you'd better use percentages) of the slide block to set slide positions. To provide a smooth slide however, let the CSS engine interpolate the movement between two values of the left property:

.slide {
transition: left 1s ease;
}

We may also want to animate it automatically. To do so, just define the key values to interpolate between. With our two images to slide, we will define two steps only: one where the slider is at the top most left, and another where the slider starts back at 100% of its container (the screen) width.

@keyframes sliding {
0% {
left: 0;
}
100% {
left: -100%;
}
}

Note that this key frames definition is for reference purpose from any selector, and so is not to be declared inside a specific one.

Then add the animation property on the slider. For example to loop infinitely and reversely during 2 seconds:

.slider {
animation: sliding 2s alternate infinite;
}

In the old days, you had to use vendor prefixed properties (such as -webkit-, -moz-, etc.) to make it work on any browser, and build plugins like Autoprefixer could help you to automate that. Not anymore.

Now you’re ready to improve this example further, by avoiding the screen header bar to scroll, or implementing some additional behavior on a home button click for instance.

Feel free to fork!

--

--