search
HomeWeb Front-endCSS TutorialTurning a Fixed-Size Object into a Responsive Element

Turning a Fixed-Size Object into a Responsive Element

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:

  1. calc(), a CSS function that can perform calculations, even when inputs have different units
  2. --size-divisor, a CSS custom property used with the var() function
  3. @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 , which can be given to a transform attribute in a style. Overall, this is a strong approach, but does not change the actual measurement of the CSS device. I prefer my approach, especially when working with complex UI elements rendered on the device’s “screen.”

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!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Demystifying Screen Readers: Accessible Forms & Best PracticesDemystifying Screen Readers: Accessible Forms & Best PracticesMar 08, 2025 am 09:45 AM

This is the 3rd post in a small series we did on form accessibility. If you missed the second post, check out "Managing User Focus with :focus-visible". In

Adding Box Shadows to WordPress Blocks and ElementsAdding Box Shadows to WordPress Blocks and ElementsMar 09, 2025 pm 12:53 PM

The CSS box-shadow and outline properties gained theme.json support in WordPress 6.1. Let's look at a few examples of how it works in real themes, and what options we have to apply these styles to WordPress blocks and elements.

Working With GraphQL CachingWorking With GraphQL CachingMar 19, 2025 am 09:36 AM

If you’ve recently started working with GraphQL, or reviewed its pros and cons, you’ve no doubt heard things like “GraphQL doesn’t support caching” or

Making Your First Custom Svelte TransitionMaking Your First Custom Svelte TransitionMar 15, 2025 am 11:08 AM

The Svelte transition API provides a way to animate components when they enter or leave the document, including custom Svelte transitions.

Classy and Cool Custom CSS Scrollbars: A ShowcaseClassy and Cool Custom CSS Scrollbars: A ShowcaseMar 10, 2025 am 11:37 AM

In this article we will be diving into the world of scrollbars. I know, it doesn’t sound too glamorous, but trust me, a well-designed page goes hand-in-hand

Show, Don't TellShow, Don't TellMar 16, 2025 am 11:49 AM

How much time do you spend designing the content presentation for your websites? When you write a new blog post or create a new page, are you thinking about

Building an Ethereum app using Redwood.js and FaunaBuilding an Ethereum app using Redwood.js and FaunaMar 28, 2025 am 09:18 AM

With the recent climb of Bitcoin’s price over 20k $USD, and to it recently breaking 30k, I thought it’s worth taking a deep dive back into creating Ethereum

What the Heck Are npm Commands?What the Heck Are npm Commands?Mar 15, 2025 am 11:36 AM

npm commands run various tasks for you, either as a one-off or a continuously running process for things like starting a server or compiling code.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Powerful PHP integrated development environment

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools