Intro
In the realm of web development, the concept of responsive design often presents a steep learning curve for beginners. Even after moving on to more advanced topics, many still struggle to fully grasp the essence of responsive design, a shortfall that becomes evident in their projects.
Responsive design is an elusive goal for many engineers, primarily because the crunch of deadlines often shifts their focus to functionality and how the project looks on their personal device. This narrow focus can lead to oversight of how a website or app performs across different devices.
Even established websites can falter in responsiveness. Personally, I find that the proverbial amazon.com loses its aesthetic appeal when I shrink the browser on my laptop.
That said, I don’t believe it’s too difficult nowadays to achieve a decent level of proficiency with responsive design. I just think there has been a lack of educational focus on the topic, and in presenting it in a clear comprehensive way. That is what I intend to do in this article / video.
I’ve identified seven CSS properties/concepts that one must know in order to achieve almost any responsive design. While there may be additional techniques to enhance responsiveness, these seven are comprehensive enough to tackle most scenarios. Unless you’re making your app ultra-complex, you should be able to understand and apply these concepts in a reasonable amount of time.
Of course, to truly understand these concepts, practice is essential. That's why I've put together a video tutorial to complement this guide, offering a practical demonstration of the principles discussed. Remember, with each practice session,
these concepts will become more intuitive.
Here are the main topics I’ve identified as crucial:
- Size units
- Relative to screen -
vw
, vh
- Relative to other elements - %
- The
max-width
and min-width
properties - Flexbox
- CSS grid
- Media queries
- Responsive images properties
- JavaScript for more complex responsive behaviors
Size units
Most beginners focus on creating a design that fits their screen nicely. Therefore, they don’t realize the downsides of specifying elements’ size, padding, margin, etc in exact terms, usually with pixels (px). The problem is that those elements will never change size as the screen size changes. Transitioning to using less absolute units like percentages and viewport units (vw/vh) is key for a flexible design.
Percentages
Beginners must be careful with percentages. It takes time to understand the concept of parent-child relationships and that when a percentage is given to a child, it is a percentage of the size of its parent/container (interchangeable terms), not the whole screen.
Another point here is that all the outside elements that seemingly “don’t have a
parent” actually do - the <body>
element. And the body’s size is as follows:
- Width - the width of the screen
- Height - the height of the content inside of it (0 if nothing is in the body)
Viewport width/height (vw
/vh
)
When you want an element to be sized relative to the screen, thus having no relation to the size of its direct container, you want to use vw
and vh
.
One example is the following. Let’s say your website is meant to have a <header>
then a <main>
section, and you want to specifically size the height of the header and have the main section take up the rest of the screen’s height.
One way to accomplish this is the following:
header {
height: 300px;
}
main {
height: calc(100vh - 300px);
}
One vh
unit is basically 1% of the viewport height (the height of the screen). Therefore, 100vh
means 100% of the height of the screen, and thus calc(100vh - 300px)
means “100% of the screen height minus 300px.”
This ensures the main section will take up the remainder of the height of the screen after the header.
You could also achieve this result with flex, but I’ll talk about that later. In this specific case, I think either is fine. Maybe one method will prove better as the project grows in complexity.
When to use px
Having these other options and the ones I will detail below definitely do not mean that the px unit has no place in CSS nowadays. There are still many situations in which you want something to have a specific size that doesn’t change along with the screen.
Many elements in a UI design may prefer a specific size that will never change. Often buttons are sized this way, for example.
The max-width
and min-width
properties
These properties become useful when you want an element to grow or shrink in size, but only to a certain point.
One common scenario for this is with search bars at the top of the UI. The search bar will likely take up the majority of the screen width on mobile devices. And though the search bar will be bigger for a laptop than a mobile phone, once the devices get larger, you won’t want the search bar to remain almost the full screen width.
Take a look at how Airbnb’s input bar changes (just the width of it, I mean) as the screen grows.
Mobile:
Tablet:
Big tablet / small laptop:
Laptop:
It's a little hard to tell with these images, but on mobile, the search bar takes up most of the width of the screen, but is still small in terms of px). Then it grows for tablets and small laptops. But at a certain point, it stops growing more as the screen further increases in size.
Flexbox
I count myself very lucky to have not had to learn CSS before flexbox was invented. “Flex,” for short, is an amazing method of relating elements to each other in terms of position and size.
With flex, you write display: flex;
on the parent element, then it becomes a “flex container,” and all of its direct children become “flex items.” There are several intuitive flex-related properties you can set on the flex container to describe how the flex items should behave. There are also properties you can set on the flex items themselves to distinguish their styling from the rest of the flex items.
It is common that beginners don’t understanding that the flex relationship is strictly between parent and child. Not parent and grandchild, and so on. You can have flex items that are also flex containers themselves. All that means is one element has display: flex;
and one of its children also has display: flex;
.
Here are two of the most common scenarios in which flex becomes handy:
- Flex allows you to create positional/spacial relationships between elements that are all next to or on top of each other. So if, for example, you have a few items in a row, you can space them evenly from each other in that row with just one or two simple CSS properties.
- With flex, you can easily change the direction in which sibling elements are positioned. By direction, I mean from horizontal (row) to vertical (column), or vice versa. For example, think links in a nav at the top of the screen that become organized vertically under a hamburger menu for mobile.
CSS grid
There is one shortcoming of flex, and that is when you are trying to control elements in two directions (x-axis AND y-axis) at the same time. Flex is all about defining properties for elements that are aligned along the same one axis (x-axis OR y-axis). The most common scenario for wanting to do this is when making a grid of items.
You may run into trouble when trying to ensure they’re all the same size. See the below image for an example of this.
With grid, you can just apply one or two easy CSS properties, and bam, problem solved. See below.
#card-container {
padding: 20px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 20px;
justify-content: center;
}
Note - Some people actually choose to use grid for the entire layout of their website. To be honest, I have never spent enough time to explore this option because I learned flex first (grid came out later), and flex is good for 95+% of my needs. I really have only needed grid for actual grid layouts, which are typically a subsection of my websites, if I need them at all.
There is nothing wrong with using flex and grid in different parts of your UI!
Media queries
In almost any design, you will need things to change more drastically when the screen hits a certain size. Small screens favor vertical scrolling. With larger computer screens, you can fit more elements horizontally.
With media queries, you can define what are called “breakpoints” - points at which some styles are to be overridden to accommodate the tweaked designs for other devices.
You have a choice to either create the mobile or desktop UI first, then create a breakpoint at which you define new styles to override the existing ones for the platforms that you didn’t initially design for.
Let’s use the example where for mobile devices, certain elements should be organized in a column, but on larger devices, they should be organized in a row.
Let’s assume that we have chosen “mobile first design,” which means designing the mobile UI first, then figuring out the responsiveness to achieve the larger devices’ designs. This choice, rather than designing for laptop/desktop first, is considered better today since the populus spends more time on phones than larger computers, and a company will prefer to make more users happy.
Well, the way to tell your app to change its appearance at tablet width and larger is to basically - with a media query breakpoint - say, “at this pixel width and higher, change the organization of these items to be a row now.”
This change may mean just changing a flex container’s flex-direction property from column to row, as shown below:
#flex-container {
display: flex;
flex-direction: column;
}
screen and (min-width: 768px) {
#flex-container {
flex-direction: row;
}
}
This snippet means that the element with ID “flex-container” will have flex-direction: column
; for screens less than 768px in width, but for screens with width 768px and above, the element will have flex-direction: row;
.
Side note - There are relatively standard pixel widths for each device, so you can look up the pixel width at which to set a breakpoint to indicate a transition from mobile to tablet, tablet to laptop, and so on.
Responsive images properties
Often a combination of the above properties will be used to dictate the size of images in your website, and no further CSS will be needed.
However, there are times when the image is not scaling property with the screen. I wanted to provide a couple properties you could explore when this happens.
One property is aspect-ratio
. This property allows you to define a preferred aspect ratio for images so that it always maintains the same height-to-width ratio across different screen sizes.
Another property is object-fit
, which can take values such as fill
, contain
, cover
, none
, and scale-down
, allowing for flexible control over how images adapt to different screen sizes.
JavaScript for more complex responsive behaviors
Finally, JS plays a crucial role in responsive design for more dynamic and complex adjustments that CSS alone cannot handle, allowing for custom behaviors based on user interactions or device specifications.
With JS, you can react to more event types than just screen size changes, such as button clicks, scrolling, dragging and dropping, and more.
With JS, you can write logic to dynamically adjust the sizes of elements based on whatever conditions you want. For example, you can adapt content based on the user's device, behavior, preferences, and/or location.
JS will be the bulk of the code for your UI, so if something is not easily attainable with HTML and CSS, often the solution will require JS.
Conclusion
Achieving responsive design is a balancing act, requiring a blend of CSS finesse and strategic JavaScript. By understanding and applying the seven key concepts outlined above, developers can create websites that are not only visually appealing but also adaptable across all the necessary devices.
The journey to mastering responsive design is one of continuous learning and practice. To see these concepts in action, don't forget to check out the accompanying video tutorial.
Remember that responsive design is within reach, and with each project, the process becomes more intuitive.
Hopefully I have managed to make responsive design a less foggy and daunting concept for you with this article and video.
I wish you the best of luck with your future projects, and I thank you for reading.
Until next time,
Jared