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!

Hot AI Tools

Undress AI Tool
Undress images for free

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

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

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

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

There are three ways to create a CSS loading rotator: 1. Use the basic rotator of borders to achieve simple animation through HTML and CSS; 2. Use a custom rotator of multiple points to achieve the jump effect through different delay times; 3. Add a rotator in the button and switch classes through JavaScript to display the loading status. Each approach emphasizes the importance of design details such as color, size, accessibility and performance optimization to enhance the user experience.

To deal with CSS browser compatibility and prefix issues, you need to understand the differences in browser support and use vendor prefixes reasonably. 1. Understand common problems such as Flexbox and Grid support, position:sticky invalid, and animation performance is different; 2. Check CanIuse confirmation feature support status; 3. Correctly use -webkit-, -moz-, -ms-, -o- and other manufacturer prefixes; 4. It is recommended to use Autoprefixer to automatically add prefixes; 5. Install PostCSS and configure browserslist to specify the target browser; 6. Automatically handle compatibility during construction; 7. Modernizr detection features can be used for old projects; 8. No need to pursue consistency of all browsers,

Themaindifferencesbetweendisplay:inline,block,andinline-blockinHTML/CSSarelayoutbehavior,spaceusage,andstylingcontrol.1.Inlineelementsflowwithtext,don’tstartonnewlines,ignorewidth/height,andonlyapplyhorizontalpadding/margins—idealforinlinetextstyling

Setting the style of links you have visited can improve the user experience, especially in content-intensive websites to help users navigate better. 1. Use CSS's: visited pseudo-class to define the style of the visited link, such as color changes; 2. Note that the browser only allows modification of some attributes due to privacy restrictions; 3. The color selection should be coordinated with the overall style to avoid abruptness; 4. The mobile terminal may not display this effect, and it is recommended to combine it with other visual prompts such as icon auxiliary logos.

Use the clip-path attribute of CSS to crop elements into custom shapes, such as triangles, circular notches, polygons, etc., without relying on pictures or SVGs. Its advantages include: 1. Supports a variety of basic shapes such as circle, ellipse, polygon, etc.; 2. Responsive adjustment and adaptable to mobile terminals; 3. Easy to animation, and can be combined with hover or JavaScript to achieve dynamic effects; 4. It does not affect the layout flow, and only crops the display area. Common usages are such as circular clip-path:circle (50pxatcenter) and triangle clip-path:polygon (50%0%, 100 0%, 0 0%). Notice

To create responsive images using CSS, it can be mainly achieved through the following methods: 1. Use max-width:100% and height:auto to allow the image to adapt to the container width while maintaining the proportion; 2. Use HTML's srcset and sizes attributes to intelligently load the image sources adapted to different screens; 3. Use object-fit and object-position to control image cropping and focus display. Together, these methods ensure that the images are presented clearly and beautifully on different devices.

The choice of CSS units depends on design requirements and responsive requirements. 1.px is used for fixed size, suitable for precise control but lack of elasticity; 2.em is a relative unit, which is easily caused by the influence of the parent element, while rem is more stable based on the root element and is suitable for global scaling; 3.vw/vh is based on the viewport size, suitable for responsive design, but attention should be paid to the performance under extreme screens; 4. When choosing, it should be determined based on whether responsive adjustments, element hierarchy relationships and viewport dependence. Reasonable use can improve layout flexibility and maintenance.

Different browsers have differences in CSS parsing, resulting in inconsistent display effects, mainly including the default style difference, box model calculation method, Flexbox and Grid layout support level, and inconsistent behavior of certain CSS attributes. 1. The default style processing is inconsistent. The solution is to use CSSReset or Normalize.css to unify the initial style; 2. The box model calculation method of the old version of IE is different. It is recommended to use box-sizing:border-box in a unified manner; 3. Flexbox and Grid perform differently in edge cases or in old versions. More tests and use Autoprefixer; 4. Some CSS attribute behaviors are inconsistent. CanIuse must be consulted and downgraded.
