I was in a situation recently where I wanted to show an iPhone on a website. I wanted users to be able to interact with an application demo on this “mock” phone, so it had to be rendered in CSS, not an image. I found a great library called marvelapp/devices.css. The library implemented the device I needed with pure CSS, and they looked great, but there was a problem: the devices it offered were not responsive (i.e. they couldn’t be scaled). An open issue listed a few options, but each had browser incompatibilities or other issues. I set out to modify the library to make the devices responsive.
Here is the final resizable library. Below, we’ll walk through the code involved in creating it.
The original library was written in Sass and implements the devices using elements with fixed sizing in pixels. The authors also provided a straightforward HTML example for each device, including the iPhone X we’ll be working with throughout this article. Here’s a look at the original. Note that the device it renders, while detailed, is rather large and does not change sizes.
Here’s the approach
There are three CSS tricks that I used to make the devices resizable:
- calc(), a CSS function that can perform calculations, even when inputs have different units
- --size-divisor, a CSS custom property used with the var() function
- @media queries separated by min-width
Let’s take a look at each of them.
calc()
The CSS calc() function allows us to change the size of the various aspects of the device. The function takes an expression as an input and returns the evaluation of the function as the output, with appropriate units. If we wanted to make the devices half of their original size, we would need to divide every pixel measurement by 2.
Before:
width: 375px;
After:
width: calc(375px / 2);
The second snippet yields a length half the size of the first snippet. Every pixel measurement in the original library will need to be wrapped in a calc() function for this to resize the whole device.
var(–size-divisor)
A CSS variable must first be declared at the beginning of the file before it can be used anywhere.
:root { --size-divisor: 3; }
With that, this value is accessible throughout the stylesheet with the var() function. This will be exceedingly useful as we will want all pixel counts to be divided by the same number when resizing devices, while avoiding magic numbers and simplifying the code needed to make the devices responsive.
width: calc(375px / var(--size-divisor));
With the value defined above, this would return the original width divided by three, in pixels.
@media
To make the devices responsive, they must respond to changes in screen size. We achieve this using media queries. These queries watch the width of the screen and fire if the screen size crosses given thresholds. I chose the breakpoints based on Bootstrap’s sizes for xs, sm, and so on.
There is no need to set a breakpoint at a minimum width of zero pixels; instead, the :root declaration at the beginning of the file handles these extra-small screens. These media queries must go at the end of the document and be arranged in ascending order of min-width.
@media (min-width: 576px) { :root { --size-divisor: 2; } } @media (min-width: 768px) { :root { --size-divisor: 1.5; } } @media (min-width: 992px) { :root { --size-divisor: 1; } } @media (min-width: 1200px) { :root { --size-divisor: .67; } }
Changing the values in these queries will adjust the magnitude of resizing that the device undergoes. Note that calc() handles floats just as well as integers.
Preprocessing the preprocessor with Python
With these tools in hand, I needed a way to apply my new approach to the multi-thousand-line library. The resulting file will start with a variable declaration, include the entire library with each pixel measurement wrapped in a calc() function, and end with the above media queries.
Rather than prepare the changes by hand, I created a Python script that automatically converts all of the pixel measurements.
def scale(token): if token[-2:] == ';\n': return 'calc(' token[:-2] ' / var(--size-divisor));\n' elif token[-3:] == ');\n': return '(' token[:-3] ' / var(--size-divisor));\n' return 'calc(' token ' / var(--size-divisor))'
This function, given a string containing NNpx, returns calc(NNpx / var(--size-divisor));. Throughout the file, there are fortunately only three matches for pixels: NNpx, NNpx; and NNpx);. The rest is just string concatenation. However, these tokens have already been generated by separating each line by space characters.
def build_file(scss): out = ':root {\n\t--size-divisor: 3;\n}\n\n' for line in scss: tokens = line.split(' ') for i in range(len(tokens)): if 'px' in tokens[i]: tokens[i] = scale(tokens[i]) out = ' '.join(tokens) out = "@media (min-width: 576px) {\n \ :root {\n\t--size-divisor: 2;\n \ }\n}\n\n@media (min-width: 768px) {\n \ :root {\n\t--size-divisor: 1.5;\n \ }\n}\n\n@media (min-width: 992px) { \ \n :root {\n\t--size-divisor: 1;\n \ }\n}\n\n@media (min-width: 1200px) { \ \n :root {\n\t--size-divisor: .67;\n }\n}" return out
This function, which builds the new library, begins by declaring the CSS variable. Then, it iterates through the entire old library in search of pixel measurements to scale. For each of the hundreds of tokens it finds that contain px, it scales that token. As the iteration progresses, the function preserves the original line structure by rejoining the tokens. Finally, it appends the necessary media queries and returns the entire library as a string. A bit of code to run the functions and read and write from files finishes the job.
if __name__ == '__main__': f = open('devices_old.scss', 'r') scss = f.readlines() f.close() out = build_file(scss) f = open('devices_new.scss', 'w') f.write(out) f.close()
This process creates a new library in Sass. To create the CSS file for final use, run:
sass devices_new.scss devices.css
This new library offers the same devices, but they are responsive! Here it is:
To read the actual output file, which is thousands of lines, check it out on GitHub.
Other approaches
While the results of this process are pretty compelling, it was a bit of work to get them. Why didn’t I take a simpler approach? Here are three more approaches with their advantages and drawbacks.
zoom
One initially promising approach would be to use zoom to scale the devices. This would uniformly scale the device and could be paired with media queries as with my solution, but would function without the troublesome calc() and variable.
This won’t work for a simple reason: zoom is a non-standard property. Among other limitations, it is not supported in Firefox.
Replace px with em
Another find-and-replace approach prescribes replacing all instances of px with em. Then, the devices shrink and grow according to font size. However, getting them small enough to fit on a mobile display may require minuscule font sizes, smaller than the minimum sizes browsers, like Chrome, enforce. This approach could also run into trouble if a visitor to your website is using assistive technology that increases font size.
This could be addressed by scaling all of the values down by a factor of 100 and then applying standard font sizes. However, that requires just as much preprocessing as this article’s approach, and I think it is more elegant to perform these calculations directly rather than manipulate font sizes.
scale()
The scale() function can change the size of entire objects. The function returns a
Chris Coyier prepared an example using this approach.
In conclusion
Hundreds of calc() calls might not be the first tool I would reach for if implementing this library from scratch, but overall, this is an effective approach for making existing libraries resizable. Adding variables and media queries makes the objects responsive. Should the underlying library be updated, the Python script would be able to process these changes into a new version of our responsive library.
The above is the detailed content of Turning a Fixed-Size Object into a Responsive Element. For more information, please follow other related articles on the PHP Chinese website!

CSS Grid is a powerful tool for creating complex, responsive web layouts. It simplifies design, improves accessibility, and offers more control than older methods.

Article discusses CSS Flexbox, a layout method for efficient alignment and distribution of space in responsive designs. It explains Flexbox usage, compares it with CSS Grid, and details browser support.

The article discusses techniques for creating responsive websites using CSS, including viewport meta tags, flexible grids, fluid media, media queries, and relative units. It also covers using CSS Grid and Flexbox together and recommends CSS framework

The article discusses the CSS box-sizing property, which controls how element dimensions are calculated. It explains values like content-box, border-box, and padding-box, and their impact on layout design and form alignment.

Article discusses creating animations using CSS, key properties, and combining with JavaScript. Main issue is browser compatibility.

Article discusses using CSS for 3D transformations, key properties, browser compatibility, and performance considerations for web projects.(Character count: 159)

The article discusses using CSS gradients (linear, radial, repeating) to enhance website visuals, adding depth, focus, and modern aesthetics.

Article discusses pseudo-elements in CSS, their use in enhancing HTML styling, and differences from pseudo-classes. Provides practical examples.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

Atom editor mac version download
The most popular open source editor

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

SublimeText3 Linux new version
SublimeText3 Linux latest version

ZendStudio 13.5.1 Mac
Powerful PHP integrated development environment
