How to Implement The Mobile First CSS Approach
Adopting the mobile first CSS approach is crucial as more people access the Internet via mobile phones than desktop devices. This approach helps developers refine website logic, functionality, design, accessibility, performance, and overall optimization for mobile usability.
The mobile first CSS approach focuses on optimizing the user experience for mobile devices. Developers use CSS containers or media queries to apply breakpoints for larger screens. By refining website logic, design, and performance, developers can cater to the increasingly mobile user base.
In this blog, you will learn what a mobile first CSS approach is, offering insights into its implementation and addressing the common question: Is it genuinely worthwhile? By the end of this blog, you will learn the significance of adopting a mobile first CSS approach and gain practical know-how on integrating it seamlessly into your CSS workflow.
What Is the Mobile First CSS Approach?
The mobile first CSS approach initially involves designing for mobile devices and then using media queries to adjust the layout for larger screens like tablets, laptops, or desktops. This strategy ensures that the website is optimized for mobile users while providing a good experience on larger screens.
Before mobile devices, websites were designed for desktop computers, following the Desktop First approach. With the rise of mobile phones and the need for sites to be accessible on smaller screens, responsive design was introduced. This approach allows developers to use breakpoints in CSS using media queries.
For example, when accessing a website from a desktop or laptop, the server detects the device type (mobile, tablet, desktop) through the user agent. It then loads the appropriate CSS stylesheets for that device, and CSS breakpoints are used to make the website responsive.
For instance, let’s try to access the LambdaTest website.
However, if the same website is accessed with a mobile phone, the website will display as shown below.
Here, we have used LT Browser, a mobile site tester offered by the LambdaTest platform, to check the performance of the web pages.
LT Browser helps developers and testers with responsive testing and debugging. It lets you experience how websites look on different pre-installed device viewports like mobiles, tablets, desktops, and laptops.
Each device view has its own Chrome DevTools, so you can easily find and debug issues tailored to each device’s layout. This makes testing easier and gives you the confidence to create a seamless mobile website testing experience.
The mobile version of the LambdaTest website above consists of minimal content display; the fonts, images, and icons have been made smaller with media queries as soon as they reach a specific breakpoint of the mobile device, which has a max-width of 500px.
In this blog on the mobile first CSS approach, we will learn why it is essential to start building your website with a mobile first rather than a desktop first approach.
Why Mobile First CSS Approach?
To truly understand if a mobile first CSS approach is needed, we must understand why the mobile first approach is needed. The mobile phone now plays a significant part in the consumer lifecycle, with most of the online interactivity happening through the mobile phone.
According to the StatCounter report, 59.57% of active users use mobile devices for activities such as visiting websites, online shopping, online payments, and entertainment more than desktops. This data shows that mobile devices have a wider reach than desktops or laptops yearly.
It emphasizes the importance of a mobile first approach. Focusing on mobile usability first ensures that developers prioritize functionality, features, and testing on mobile devices for the best ROI.
The mobile first CSS approach refers to the design and development strategy. It encourages developers to consider mobile devices first when building their website before desktops, which has a huge impact on the success or failure of the website.
As we have learned the importance of implementing the mobile first approach, we will learn the advantages of the mobile first CSS approach in the below section.
Advantages of the Mobile First CSS Approach
Mobile first CSS approach has many benefits for businesses and any platform looking to drive more traffic to their website. In a world where everyone has a smartphone and is quick to access information online, a mobile first approach becomes necessary.
In this section, we will list some advantages and benefits of implementing a mobile first approach in CSS.
Responsive Design
Responsive design ensures that content is easily accessible and readable on all the different screen sizes. With the mobile first CSS approach, optimizing the content for different device screens becomes easier. As new mobile devices with different screen sizes are introduced, responsive design helps ensure that websites and content remain compatible and accessible.
A mobile-friendly website is easily accessible on various devices, including computers, tablets, and smartphones. Unlike a traditional website that may require extra effort to access content on smaller screens, a mobile-friendly website remains fully functional as its layout adjusts automatically to fit any device’s screen size.
However, you can validate your website’s responsiveness by performing responsive testing on different screen sizes and devices. This helps ensure your website works and looks as expected across varying screen sizes, providing a better user experience.
Website Accessibility
The mobile first CSS approach can benefit people with disabilities or visual impairments. By focusing on mobile first design, developers can consider factors such as color contrast and WAI-ARIA roles, ensuring a well-functioning and accessible website.
To validate the accessibility of your websites across different screen sizes and follow accessibility standards, you can perform accessibility testing. Tools such as Accessibility DevTool by LambdaTest help you maintain accessibility standards and ensure your site is accessible to all.
It is a Chrome extension that helps check functionality and UI based on accessibility testing standards and identify and report accessibility issues.
With this extension, you can conduct Full Page Scans to evaluate entire web pages or Partial Page Scans to target specific accessibility issues. The Accessibility DevTools dashboard provides a detailed summary and breakdown of your website’s performance, helping you identify and address accessibility issues effectively.
If you wish to use this Chrome extension, click the Install Accessibility DevTools button below.
You can watch this video tutorial to learn the importance of making your website or application accessible to everyone, including people with disabilities.
SEO Benefits
The mobile first CSS approach benefits Search Engine Optimization (SEO), particularly with Google’s mobile-first indexing. When content is well-optimized for mobile devices, Googlebot and other search engine platforms can easily crawl and index the content. This can lead to higher rankings and better visibility for your website.
Implementing Mobile First CSS Approach in CSS
By now, you should better understand the term Mobile First and its relation to the mobile first CSS approach. We will learn how to implement this approach using container and media queries, which help apply breakpoints to style or render elements differently on larger screens.
Container Queries
In this section, you will learn how to implement the mobile first CSS approach using CSS container queries.
CSS container queries set styles for elements based on the size of the element’s parent or container (width and height), unlike media queries, which detect changes in the viewport width or height. For example, we can adjust the font size of a child element based on changes in the parent container’s size (shrinking or growing).
The container queries use a single property called a container, a shorthand property where we specify the container’s name and type. This property is applied within the parent or root element of the actual element.
/*Shorthand property*/
Container: sidebar / inline-size;
/*Shorthand properties*/
container-type: inline-size;
container-name: sidebar;
}
After the container property has been specified, we use the @container at rule to apply breakpoints to the target element we want to change.
@container sidebar (min-width: 500px) {
.child p {
font-size: 2em;
}
}
Result:
Now, let’s see how to implement a mobile first CSS approach by creating a simple landing page using container queries as breakpoints.
To get started, generate a simple HTML template and type the code below.
HTML:
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Laptop Gallery</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" integrity="sha512-SnH5WK+bZxgPHs44uWIX+LLJAJ9/2PkPKZ5QiAj6Ta86w+fsb2TkcmfRyVX3pBnMFcV7oQPJkl9QevSCWr3W6A==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="/main.js" defer></script>
</head>
<body>
<div>
<!-- Navbar -->
<main class="navabr-container">
<header>
<nav>
<section class="logo">
<div>
<img src="https://raw.githubusercontent.com/alex-anie/loptops/36b8706025f934546467b5bfa77b0eb21f120616/icons/logo.svg" alt="lambdaTest logo" />
</div>
</section>
<section class="menu-bar">
<section class="nav-links positioning-navlinks">
<ul>
<li>
<a href="#">Platform</a>
</li>
<li>
<a href="#">Enterprise</a>
</li>
<li>
<a href="#">Resources</a>
</li>
<li>
<a href="#">Blog</a>
</li>
<li>
<a href="#">Contact</a>
</li>
</ul>
</section>
<section class="search-container">
<div class="search-wrapper">
<input type="search" placeholder="Search the site..." >
<i class="fa-solid fa-magnifying-glass"></i>
</div>
</section>
<section class="hamburger-menu">
<div>
<i class="fa-solid fa-bars"></i>
</div>
</section>
</section>
</nav>
</header>
</main>
</body>
</html>
The HTML code above contains a
element that serves as the parent container for the entire navbar, and nested inside this element is a element. The element has the following elements that serve as component elements for the navbar.
section class=”logo”: The <section> element with a class of logo acts as the container for the website logo, allowing us to apply styling for its display. Inside this element, there are two nested elements: a <div> and an <img> element.
section class=”menu-bar”: The <section> element, with a class of menu-bar contains all the nav links of the navbar. With this <section> element we can directly apply style targeted at the nav links on the navbar.
section class=”search-container”: The <section> element with a class of search-container serves as the container for the search bar. With this <section> element, we can style the nav bar’s search bar.
section class=”hamburger-menu”: The <section> element with a class of hamburger-menu serves as the nav link toggle button on mobile. Nested inside this element is a single icon element <i> tag.
CSS:
*,*::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
a {
color: #000;
text-decoration: none;
}
img {
width: 100%;
}
@import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@300..700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+Display:ital,wght@0,100..900;1,100..900&family=Pinyon+Script&family=Satisfy&display=swap');
:root {
/* Colors */
--slate-0-5: rgb(248 250 252);
--slate-01: rgb(241 245 249);
--slate-02: rgb(226 232 240);
--slate-03: rgb(203 213 225);
--slate-04: rgb(148 163 184);
--slate-05: rgb(100 116 139);
--slate-06: rgb(71 85 105);
--slate-07: rgb(51 65 85);
--slate-08: rgb(30 41 59);
--slate-09: rgb(15 23 42);
--slate-09: rgb(2 6 23);
/* Fonts */
--quicksand: "Quicksand", sans-serif;
--nato-serif-display: "Noto Serif Display", serif;
}
body {
width: 100vw;
container: heroSectionContainer / inline-size;
}
header {
background-color: var(--slate-0-5);
padding: 1em 0;
position: fixed;
left: 0;
top: 0;
width: 100vw;
z-index: 9999;
}
header nav {
width: 80%;
margin: 0 auto;
display: flex;
justify-content: space-between;
}
/* This wrappers around the navlinks, search and hamburger */
.menu-bar {
width: 100%;
height: 100%;
display: flex;
column-gap: 1.5em;
justify-content: end;
-webkit-user-select: none;
user-select: none;
container: menubar / inline-size;
}
.positioning-navlinks {
display: none;
}
.nav-links ul li {
list-style-type: none;
letter-spacing: 1px;
}
.nav-links ul li a {
color: var(--slate-05);
text-decoration: none;
text-transform: uppercase;
font-size: 12px;
font-family: var(--quicksand);
}
.nav-links ul li a:hover {
color: var(--slate-09);
}
/* Search Icon */
.search-wrapper {
background-color: var(--slate-02);
border-radius: 100px;
padding: 0.5em;
transform: translateY(-5px);
}
.search-wrapper input {
width: 85%;
border: 0;
outline: none;
background-color: transparent;
}
.search-wrapper i {
color: var(--slate-05);
}
@container menubar (min-width: 500px){
.positioning-navlinks {
display: block;
}
.positioning-navlinks ul {
display: flex;
flex-direction: row;
justify-content: end;
align-items: start;
gap: 2em;
}
.search-wrapper {
display: none;
}
.hamburger-menu {
display: none;
}
}
/* Hamburger */
.hamburger-menu i {
color: var(--slate-05);
}
From the CSS code above, container queries are used as breakpoints to implement the mobile first CSS approach.
- @container menubar (min-width: 500px): With the @container rule, you can re-declare the styles on the navbar to accommodate the changes in the size of the navbar container.
From the highlighted code above, the styles specified within the @container rule are re-declared to re-align target elements as soon as the containing elements change sizes.
Mobile Result:
From the mobile view, the navlinks are set to display:none. It will prevent the navbar from having clustered navlink items.
However, the code should look like this on your desktop as soon as you expand your browser.
From the desktop view, the search bar and hamburger icon are set to display:none; this will give room for the navlinks on the navbar.
Now that we have completed the navbar, let’s create a hero section and see how to implement a mobile first CSS approach on a landing page.
HTML:
<!-- Hero Section -->
<main class="hero-section-container">
<section class="hero-section">
<aside class="hero-left-content">
<div class="hero-text">
<h1>Next-Generation Mobile Apps and Cross Browser <span>Testing Cloud</span></h1>
<div class="dash"></div>
<p>
Deliver unparalleled digital experience with our next-gen
AI-powered testing cloud platform. Ensure exceptional user
experience across all devices and browsers.</p>
</div>
<div class="hero-buttons">
<a href="https://accounts.lambdatest.com/dashboard">
<div class="img-div">
<img src="https://raw.githubusercontent.com/alex-anie/loptops/36b8706025f934546467b5bfa77b0eb21f120616/icons/google_favicon.svg" alt="">
</div>
<div class="text">Start free with Google</div>
</a>
<a href="https://accounts.lambdatest.com/dashboard">
<span>Start free with Email</s>
</a>
</div>
<div class="corporate-logo">
<p>Trusted by 2M+ users globally</p>
<div>
<img src="https://raw.githubusercontent.com/alex-anie/loptops/36b8706025f934546467b5bfa77b0eb21f120616/icons/Microsoft.svg" alt="Microsoft Logo">
<img src="https://raw.githubusercontent.com/alex-anie/loptops/36b8706025f934546467b5bfa77b0eb21f120616/icons/Vimeo.svg" alt="Vimeo Logo">
<img src="https://raw.githubusercontent.com/alex-anie/loptops/36b8706025f934546467b5bfa77b0eb21f120616/icons/Nvidia.svg" alt="Nvidia Logo">
<img src="https://raw.githubusercontent.com/alex-anie/loptops/36b8706025f934546467b5bfa77b0eb21f120616/icons/Telstra.svg" alt="Telstra Logo">
<img src="https://raw.githubusercontent.com/alex-anie/loptops/36b8706025f934546467b5bfa77b0eb21f120616/icons/rubrik.svg" alt="Rubrik logo">
</div>
</div>
</aside>
<aside class="hero-right-content">
<div>
<img src="https://raw.githubusercontent.com/alex-anie/loptops/main/lambdaTest/home_banner.webp" alt="">
</div>
</aside>
</section>
</main>
From the HTML code above, we focused on the hero section of the website, and the code is broken down as follows:
main class=”hero-section-container”: The <main> element with a class of hero-section-container, serves as the container for the entire hero section.
section class=”hero-section”: This <section> element is the direct child of the <main> element. This element has a class of hero-section and is used as a wrapper to wrap around two elements, the <aside class=”hero-left-content”> and <aside class=”hero-right-content”>, respectively.
aside class=”hero-left-content”: This <aside> element with a class of hero-left-content serves as a wrapper element for the text content, buttons, logo, and icon elements on the top of the hero section on mobile and on the desktop display version it will be in the left.
aside class=”hero-right-content”: This <aside> element with a class of hero-right-content serves as the wrapper of the hero image in the hero section. On mobile, it is positioned directly below the hero-left-content element, and on the desktop view, it will be on the right side of the hero section.
CSS:
.hero-section {
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
place-content: center;
gap: 4em;
width: 90vw;
height: 100vh;
margin: 12em auto;
}
@container heroSectionContainer (min-width: 900px){
.hero-section {
grid-template-columns: repeat(2, minmax(0, 1fr));
margin: 2em auto;
}
}
.hero-left-content {
display: flex;
flex-direction: column;
row-gap: 3em;
}
.hero-right-content {
width: 100%;
}
.hero-right-content div img {
width: 100%;
object-fit: cover;
}
.hero-section .hero-text h1{
font-size: 2em;
font-weight: bold;
font-family: Arial, Helvetica, sans-serif;
}
.hero-section .hero-text span {
background: linear-gradient(91.42deg, #2b56f3 18.38%, #a505d8 62.2%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-section .hero-text p {
font-size: 14px;
font-family: Arial, Helvetica, sans-serif;
color: rgb(37, 36, 36);
margin-top:1em;
}
.hero-section .hero-buttons {
display: flex;
gap: 1em;
}
.hero-section .hero-buttons a:first-child {
border: 2px solid #000;
border-radius: 15px;
background-color: white;
text-decoration: none;
display: flex;
gap: 5px;
}
.hero-section .hero-buttons a:first-child:hover {
border: 2px solid #2b56f3;
}
.hero-section .hero-buttons a:first-child:hover .text {
background: linear-gradient(91.42deg, #2b56f3 18.38%, #a505d8 62.2%);
}
.hero-section .hero-buttons a:first-child .img-div {
width: 30px;
padding: 5px;
margin: 5px;
}
.hero-section .hero-buttons a:first-child img {
width: 100%;
}
.hero-section .hero-buttons a:first-child .text {
display: inline-block;
background-color: #000;
color: white;
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
padding: 5px 10px;
line-height: 30px;
}
.hero-section .hero-buttons a:last-child {
text-decoration: none;
color: #000;
background-color: white;
line-height: 30px;
padding: 5px 10px;
border-radius: 15px;
border: 2px solid #2b56f3;
position: relative;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
}
.hero-section .hero-buttons a:last-child:hover {
background: linear-gradient(90deg,#235af4,#a00ada);
color: #fff;
}
.hero-section .hero-buttons a:last-child::before {
content: "";
height: 40px;
position: absolute;
top: -1px;
right: -1px;
left: -1px;
bottom: -1px;
border-radius: 5px;
padding: 1px;
z-index: -1;
background: linear-gradient(90deg,#235af4,#a00ada);
filter: blur(10px);
}
.hero-section .corporate-logo p {
font-size: 14px;
font-family: Arial, Helvetica, sans-serif;
color: rgb(33, 34, 34);
}
.hero-section .corporate-logo div {
display: flex;
gap: 1em;
}
.hero-section .corporate-logo div img {
height: 100%;
}
The CSS code above contains styles for the hero section and is as follows;
- hero-section:Here, the element with a class of hero-section is targeted and converted into a grid container by applying a display: grid style. The grid-template-columns property is set to repeat(1, minmax(0, 1fr)), which means the grid items will repeat once in a column with a minimum width of 0 and a maximum width of 1 fractional unit (1fr), ensuring they take up equal space within the grid container.
To learn more about the repeat() function and how it can be used with various CSS Grid properties such as min-content, max-content, auto, auto-fill, auto-fit, and more, follow this guide on the CSS Grid repeat() function. This guide provides detailed insights on making layouts flexible based on any given content and screen size.
Mobile Result:
From the highlighted code above the @container heroSectionContainer (min-width: 900px): you specify a container query to apply new styles as soon as the specified element min-width grows above 900px. The grid-template-columns: repeat(2, minmax(0, 1fr)), means that the specified element should split into two column grid side by side.
Desktop Result:
From the display above, we move from a mobile point of view of a one-column view to a column view on a desktop. Mobile first can easily be achieved if we take care of the mobile usability first and then apply breakpoints with CSS container query functions as indicated above.
Enhance your testing efficiency with powerful Selenium WebDriver commands.
Media Queries (min-width)
CSS media queries allow developers to control how content is displayed and which content to display based on the viewport width or height of the device loading the content. Essentially, it makes it easy to determine how content should respond to the changes on the device viewport.
From a mobile first CSS approach, styling is implemented on a small screen (mobile devices). Then, with the help of min-width in media queries, styles are re-declared to determine how content should be displayed on larger screen sizes such as tablets and desktops.
HTML :
<!-- Our Services -->
<main class="our-services">
<article>
<section class="image-wrapper">
<div>
<img src="https://github.com/alex-anie/loptops/blob/main/lambdaTest/ai-index.png?raw=true" alt="">
</div>
</section>
<section class="content">
<div>
<div class="our-services-text utl-uppercased-text">
<p class="">INTRODUCING</p>
<span class="utl-dash dash"></span>
</div>
<div>
<h1 class="utl-script-text script-text">Introducing Test<br/> Intelligence <span class="utl-script-italic">Platform</span></h1>
<p class="delivery-text">
<span class="utl-dash dash"></span>
<span class="utl-uppercased-text "> Designed to learn and evolve with each test execution, it fine-tunes
its recommendations while augmenting its predictive capabilities:</span>
</p>
<ul class="product-list">
<li class="utl-uppercased-text">AI-Powered Root Cause Analysis (RCA)</li>
<li class="utl-uppercased-text">Intelligent Flakiness Detection</li>
<li class="utl-uppercased-text">Classification Of Failed Actions</li>
</ul>
</div>
</div>
</section>
</article>
</main>
From the HTML code above, we focused on the Our Services section of the website, and the code is broken down as follows:
main class=”our-services”: This <main> element, with a class of our-services, serves as the container element for all elements in the our-services section. Nested inside this element is an <article> element as a direct child.
articles: This <article> element is used as a container for both the section class=”image-wrapper” and section class=”content” element.
section class=”image-wrapper”: This <section> element with a class of image-wrapper serves as a wrapper element for the display image in the our-services section. With this element, the image can be sized to take up the parent’s full width.
section class=”content”: This <section> element, with a class of content, serves as a wrapper element for the content in the our-services section. With this, child elements can easily be positioned within their parent container.
CSS:
/* Our Services */
.our-services {
width: 100vw;
background-color: var(--slate-02);
padding: 2em 0;
}
.image-wrapper div img {
width: 100%;
}
.our-services article {
width: 80%;
margin: 0 auto;
}
.our-services .our-services-text {
margin-bottom: 1em;
}
.our-services-text .dash {
margin: 1em 0;
}
.our-services .delivery-text {
margin: 1em 0;
}
.our-services .our-services-text p {
margin-top: 2em;
}
.delivery-text .dash {
transform: translateY(-3px);
margin-right: 0.5em;
}
.our-services .product-list li {
list-style-type: none;
text-indent: 4em;
line-height: 1.8em;
}
.our-services .product-list li::before {
content: '✅';
}
@media (min-width: 800px){
.our-services article {
width: 80%;
margin: 2em auto;
display: grid;
grid-template-columns: repeat(3, 300px);
gap: 2em;
place-content: center;
}
.our-services .image-wrapper {
grid-column: span 1;
}
.our-services .content {
grid-column: span 2;
margin-right: 2em;
}
}
/* Utilities Styles */
.utl-uppercased-text {
font-family: var(--quicksand);
text-transform: uppercase;
font-size: 12px;
color: var(--slate-06);
letter-spacing: 1.5px;
text-wrap: wrap;
}
.utl-dash {
display: inline-block;
width: 4em;
height: 1px;
background-color: var(--slate-08);
}
.utl-script-text {
font-size: 1.8em;
font-family: var(--nato-serif-display);
font-weight: 300;
color: var(--slate-08);
}
.utl-script-italic {
font-style: italic;
}
Here, we have applied a simple media query @media (min-width: 800px) to the specified element as soon as the browser viewport is greater than 800px, and once this occurs, the specified styles on the media query take effect.
From the highlighted code above media query breakpoint, the our-service article element is set to a three-column grid with 300px.
From the mobile preview above, the image-wrapper and the content element are stacked. This helps the content fit well on mobile devices.
Desktop Result:
From the result above, the desktop preview is set to display a grid to use the available space on the desktop.
Let’s see more examples of how to use min-width in a media query.
The next example is a simple four-image display, where we apply all images on a single column on mobile and a two-column grid on a desktop.
HTML:
<!-- Products Lists-->
<main class="gallery-section">
<section>
<div class="hyper-execute card">
<h1>HyperExecute</h1>
<div>
<img src="https://github.com/alex-anie/loptops/blob/main/lambdaTest/hyperexecute-index.png?raw=true" alt="">
</div>
</div>
<div class="live-testing card">
<h1>Live Testing</h1>
<div>
<img src="https://github.com/alex-anie/loptops/blob/main/lambdaTest/live-testing.png?raw=true" alt="">
</div>
</div>
<div class="mobile-app-testing card">
<h1>Mobile App Testing</h1>
<div>
<img src="https://github.com/alex-anie/loptops/blob/main/lambdaTest/mobile-app-index.png?raw=true" alt="">
</div>
</div>
<div class="visual-regression-cloud card">
<h1>Visual Regression Cloud</h1>
<div>
<img src="https://github.com/alex-anie/loptops/blob/main/lambdaTest/visual-index.png?raw=true" alt="">
</div>
</div>
</section>
</main>
The HTML code above is implemented as follows.
- main class=”gallery-section”: This element with a class of gallery-section serves as the container for all elements in the product list section. Nested within this element is a element.
CSS:
/* Gallery Section */
.gallery-section {
background-color: var(--slate-01);
width: 100%;
}
.gallery-section section {
width: 80%;
margin: 0 auto;
padding: 2ch;
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
gap: 2em;
place-content: center;
place-items: center;
}
.gallery-section section .card {
width: 300px;
background-color: white;
padding: 1em;
border-radius: 20px;
box-shadow: 2px 2px 2px rgba(0,0,0,0.5);
}
.gallery-section section .card h1 {
font-family: Arial, Helvetica;
font-size: 14px;
color: white;
background-color: var(--slate-04);
padding: 10px;
border-radius: 10px;
}
.gallery-section section .card img {
width: 100%;
}
@media (min-width: 800px ){
.gallery-section section {
grid-template-columns: repeat(2, 1fr);
place-content: center;
place-items: center;
}
}
From the CSS code above, media queries are used as breakpoints to implement the mobile first CSS approach, as follows.
Here, we have applied a simple media query @media (min-width: 800px) to the specified element as soon as the browser viewport is greater than 800px, and once this occurs, the specified styles on the media query take effect.
From the highlighted code above for the media query breakpoint, the gallery-section class element is set to a two-column grid as soon as its width exceeds 800px.
Mobile Result:
Desktop Result:
You can do more with min-width in media queries to make the content on the page more mobile first.
The next example below demonstrates implementing a mobile first CSS approach on a blog element. Here, you ensure each post is on a single column on mobile, two columns on tablet, and three columns on desktop.
HTML:
<!-- Card Section -->
<main class="card-section">
<article>
<section class="section-header">
<div>
<h1 class="utl-uppercased-text">Blog update</h1>
<span class="utl-dash dash"></span>
</div>
<div class="">
<h1 class="utl-script-text">Stay always updated <span class="utl-script-italic">As a Dev</span></h1>
</div>
</section>
<section class="card-wrapper">
<div class="card c1">
<div class="card-header">
<img src="https://raw.githubusercontent.com/alex-anie/nonso-amadi-portfolio/main/public/blogImg/center-image-on-the-web.png" alt="">
<span class="icon-wrapper">
<i class="fa-solid fa-heart"></i>
</span>
</div>
<div class="card-body">
<h3>Centering an Image in CSS: A Detailed Guide</h3>
<em>By: Alex Anie</em>
<p>Images are widely used on websites and play an important role in helping users understand and find different types of information on the web. Therefore, proper alignment of images on the websites is crucial to avoid issues like overflow or unnecessary scrolling caused by large images....</p>
</div>
<div class="btn-wrapper">
<a href="https://www.lambdatest.com/blog/centering-an-image-in-css/" target="_blank">
<button>Read More</button>
</a>
</div>
</div>
<div class="card c2">
<div class="card-header">
<img src="https://raw.githubusercontent.com/alex-anie/nonso-amadi-portfolio/main/public/blogImg/35-buttons.png" alt="">
<span class="icon-wrapper">
<i class="fa-solid fa-heart"></i>
</span>
</div>
<div class="card-body">
<h3>41 Best CSS Button Hover Effects in 2024</h3>
<em>By: Alex Anie</em>
<p>Buttons are everywhere on the web; they have proven to be an indispensable component of modern web design. Buttons are incorporated into websites, web apps, as well as mobile and desktop applications. These buttons serve as the navigation of every website and mobile application...</p>
</div>
<div class="btn-wrapper">
<a href="https://www.lambdatest.com/blog/best-css-button-hover-effects/" target="_blank">
<button>Read More</button>
</a>
</div>
</div>
<div class="card c3">
<div class="card-header">
<img src="https://raw.githubusercontent.com/alex-anie/nonso-amadi-portfolio/main/public/blogImg/carousels-accessibility.png" alt="">
<span class="icon-wrapper">
<i class="fa-solid fa-heart"></i>
</span>
</div>
<div class="card-body">
<h3>Building Accessible Carousels: A Step-By-Step Guide</h3>
<em>By: Alex Anie</em>
<p>Carousels are effective in conveying pieces of information in a concise format on the web page. Many organizations find value in using carousels to showcase their product offerings. This feature has proven to be a valuable asset for driving conversions and enhancing user engagement</p>
</div>
<div class="btn-wrapper">
<a href="https://www.lambdatest.com/blog/accessible-carousels/" target="_blank">
<button>Read More</button>
</a>
</div>
</div>
</section>
</article>
</main>
<footer>
<section>
<div>
<p>Made with <i class="fa-solid fa-heart"></i> by Alex Anie</p>
</div>
</section>
</footer>
The HTML code above is implemented as follows.
main class=”card-section”: The <main> element with a class of card-section serves as the parent container for all elements in the card section.
article: The <article> element serves as a container element for the <section class=”section-header”> element and the <section class=”card-wrapper”>.
section class=”section-header”: This element serves as the wrapper element for the heading content on the blog section. Nested within are "<h1 class=”utl-uppercased-text”>, <span class=”utl-dash dash”> and <h1 class=”utl-script-text”>"
section class=”card-wrapper”: This element is the wrapper element for the four card elements in the blog section. With this element, each blog post can be positioned with min-width at a specified breakpoint.
CSS :
/* Card Section */
.card-section {
width: 100vw;
background-color: var(--slate-02);
}
.card-section article {
width: 80%;
margin: 0 auto;
padding: 2em 0;
}
.card-section .section-header {
display: flex;
justify-content: start;
flex-direction: column;
row-gap: 1em;
}
.card-section .card-wrapper {
display: grid;
grid-template-columns: repeat(1, 300px);
justify-content: space-around;
row-gap: 2em;
margin: 2em 0;
}
.card-section .card {
background-color: white;
}
.card-section .icon-wrapper {
display: inline-block;
background-color: var(--slate-09);
padding: 0.4em;
transform: translateY(-33px);
}
.card-section .icon-wrapper i {
color: var(--slate-0-5);
}
.card-section .card-body h3 {
font-family: var(--quicksand);
font-size: 16px;
color: var(--slate-07);
}
.card-section .card-body {
padding: 1em;
}
.card-section .card-body p {
font-family: var(--quicksand);
font-size: 13px;
color: var(--slate-08);
font-weight: lighter;
line-height: 20px;
}
.card-section .card-body em {
margin: 0.4em 0;
display: inline-block;
}
.card-section .btn-wrapper {
display: flex;
justify-content: end;
}
.card-section .btn-wrapper button {
text-transform: uppercase;
font-size: 12px;
border: none;
background-color: transparent;
border-bottom: 2px solid var(--slate-08);
padding-bottom: 2px;
cursor: pointer;
margin:1em;
transition: background 0.5s ease;
}
.card-section .btn-wrapper button:hover {
background-color: var(--slate-08);
color: var(--slate-0-5);
}
@media (min-width: 600px) {
.card-section .section-header {
flex-direction: row;
justify-content: space-between;
margin-bottom: 2em;
}
.card-section .card-wrapper {
grid-template-columns: repeat(2, 300px);
column-gap: 2em;
justify-content: space-between;
}
}
/* Desktop */
@media (min-width: 1020px) {
.card-section .card-wrapper {
grid-template-columns: repeat(3, 300px);
column-gap: 2em;
justify-content: space-between;
}
}
footer {
width: 100vw;
background-color: var(--slate-08);
padding: 1em 0;
}
footer section {
display: flex;
justify-content: center;
}
footer section p{
font-family: var(--quicksand);
color: var(--slate-0-5);
}
The above CSS is implemented as follows:
card-section: The element with the card-section class is applied a width of 100vw to take the full width of the browser viewport and a background-color of light slate color.
card-section article: The
element takes a width of 80%, the margin of 0 auto will align the element and the content nested inside it to the middle of its parent element and leave an equal amount of space between the left and right side of the element with a of padding: 2em 0.
card-section section-header: With this element, we applied a display flex to the heading elements, justify-content of start, and flex-direction to column to stack each heading text on top of the other on mobile. A row-gap of 1em to add a space between the headings on the row axis.
card-section card-wrapper: This element with a class of card-wrapper serves as the wrapper for the blog elements on the page. Here, we applied a display of grid, grid-template-columns of repeat(1, 300px). This will size all blog elements with a width of 300px and align them in a single vertical column. A row-gap of 2em to add white space between the blog elements and a margin of 2em 0;
Mobile Result:
From the highlighted code, the @media (min-width: 600px) rule sets a breakpoint for a minimum width of 600px, which will take effect when the browser viewport size is above 600px. This breakpoint is typically targeted at tablet devices.
Within this breakpoint, the card-section and section-header classes are adjusted. The flex-direction is set to row, which aligns the two heading texts to display side by side horizontally. The justify-content: space-between property is applied to add space between both heading texts, and a margin-bottom of 2em is added to create extra white space outside of the element box.
Mobile Result:
From the highlighted code above, the @media (min-width: 1020px) rule sets a breakpoint for a minimum width of 1020px, which will take effect when the browser viewport size is above 1020px. This breakpoint is specifically targeted at desktop devices.
Within this breakpoint, the grid-template-columns property is adjusted to repeat(3, 300px), which means the grid items will display in three columns on a desktop device, each column with a width of 300px.
Desktop Result:
In the below section, we will learn how to implement the desktop-first CSS approach in detail using media queries (max-width).
Implementing Desktop First CSS Approach in CSS
Now that we better understand how to implement a mobile first approach. In this section, we will learn how to implement a desktop first approach. It will help to distinguish the difference between desktop and mobile first approaches.
Want to boost your coding productivity? Discover the best JavaScript tools to streamline your workflow. Start now!
Media Queries (max-width)
max-width in media query is used to set the styles when the browser viewport width gets to a maximum unit or lower. It is used to implement styles for the desktop screen. For example, @media (max-width: 800px) instructs the browser to apply a different style when the website is loaded on a device that is exactly 800px wide or narrower.
HTML:
<body>
<main class="container">
<header class="header">
<!-- Card One -->
<section class="Card__one card__body">
<div class="card_hero_section">
<h3 class="lambdaTest">LambdaTest</h3>
<img src="https://github.com/alex-anie/loptops/blob/main/lambdaTest/live-testing.png?raw=true" alt="">
<a href="https://www.lambdatest.com/online-browser-testing">
<button class="card_btn">Learn More</button>
</a>
</div>
<span class="sample_text">Live Testing</span>
<p class="sample_para">Perform live interactive cross-browser testing of your public or locally hosted websites and web apps on 3000+ real mobile and desktop browsers running on real operating system.</p>
</section>
<!-- Card Two -->
<section class="Card__three card__body">
<div class="card_hero_section">
<h3 class="lambdaTest">LambdaTest</h3>
<img src="https://github.com/alex-anie/loptops/blob/main/lambdaTest/Automation-testing-online.png?raw=true" alt="">
<a href="https://www.lambdatest.com/automation-testing">
<button class="card_btn">Learn More</button>
</a>
</div>
<span class="sample_text">Automated Testing</span>
<p class="sample_para">Perform automated browser tests on a scalable, secure, and reliable automation cloud. Run Selenium, Cypress, Appium, Hyperexecute, Playwright, and Puppeteer tests at scale on 3000+ browsers and devices.</p>
</section>
<!-- Card Three -->
<section class="Card__three card__body">
<div class="card_hero_section">
<h3 class="lambdaTest">LambdaTest</h3>
<img src="https://github.com/alex-anie/loptops/blob/main/lambdaTest/mobile-app-index.png?raw=true" alt="mobile-app-index">
<a href="https://www.lambdatest.com/mobile-app-testing">
<button class="card_btn">Learn More</button>
</a>
</div>
<span class="sample_text">Mobile App Testing</span>
<p class="sample_para">Perform live interactive testing of your mobile apps on a multitude of Android and iOS devices. Test and debug your mobile apps faster on both Emulators/Simulators or online real device cloud.</p>
</section>
<!-- Card Four -->
<section class="Card__four card__body">
<div class="card_hero_section">
<h3 class="lambdaTest">LambdaTest</h3>
<img src="https://github.com/alex-anie/loptops/blob/main/lambdaTest/hyperexecute-index.png?raw=true" alt="hyperexecute-index">
<a href="https://www.lambdatest.com/hyperexecute">
<button class="card_btn">Learn More</button>
</a>
</div>
<span class="sample_text">HyperExecute</span>
<p class="sample_para">Blazing fast AI-powered test execution & orchestration on cloud that will beat your local test execution speeds. A LambdaTest exclusive platform that is guaranteed faster than any other cloud grid offering.</p>
</section>
<!-- Card Five -->
<section class="Card__five card__body">
<div class="card_hero_section">
<h3 class="lambdaTest">LambdaTest</h3>
<img src="https://github.com/alex-anie/loptops/blob/main/lambdaTest/visual-index.png?raw=true" alt="">
<a href="https://www.lambdatest.com/smart-visual-ui-testing">
<button class="card_btn">Learn More</button>
</a>
</div>
<span class="sample_text">Visual Regression Cloud</span>
<p class="sample_para">Visual Regression Cloud
Perform AI-powered Visual regression testing to prevent costly visual bugs from escaping into production. Get insights, spot bugs in visual changes on every code change.</p>
</section>
<!-- Card Six -->
<section class="Card__five card__body">
<div class="card_hero_section">
<h3 class="lambdaTest">LambdaTest</h3>
<img src="https://github.com/alex-anie/loptops/blob/main/lambdaTest/ai-index.png?raw=true" alt="">
<a href="https://www.lambdatest.com/test-analytics">
<button class="card_btn">Learn More</button>
</a>
</div>
<span class="sample_text">AI-Powered Test Analytics</span>
<p class="sample_para">Make informed decisions with detailed Test Analytics & Observability Suite. Access vital information including test inconsistencies, number of tests, and tests categorized by their status and environments</p>
</section>
</header>
</main>
</body>
The HTML code above is implemented as follows:
main class=”container”: This element with a class of container serves as the root element to all elements on the page.
header class=”header”: This element with a class of header serves as the direct containing element for all the card elements on the page. With this element, we can apply a CSS Grid to align individual cards across the parent container. Nested within this element are six elements that serve as a card component.
CSS:
*, *::after, *::before {
box-sizing: inherit;
padding: inherit;
margin: inherit;
}
html {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
font-family: calibri;
background-color: #bdbdbd;
}
.header {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.container {
width: 70%;
margin: 0 auto;
}
.card__body {
width: 18.75em;
background-color: #fff;
margin: 10px;
padding:4px 3px;
border-radius: 10px;
cursor: pointer;
}
.card__body:hover {
box-shadow: 2px 1px 17px 1px rgba(0, 0, 0, 0.3);
}
img {
width: 100%;
}
.card_hero_section {
background-color: rgb(3, 52, 80);
box-shadow: 2px 1px 17px 1px rgba(0,0,0, 0.3);
border-radius: 3px;
background-image: url('https://user-images.githubusercontent.com/78242022/241960972-8df69d68-13b8-41a1-9a8f-610b32f1ba1d.png');
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
background-blend-mode: overlay;
}
.card_hero_section:hover {
box-shadow: none;
}
/* Card Button */
.card_btn {
background-color: #0ebac5;;
color: #fff;
border-radius: 3px;
padding: 5 20px;
border: none;
transition: background 0.5s ease-in;
}
.card_btn:hover {
background-color: #fff;
color: #09162c;
}
.sample_text {
font-family: Arial, Helvetica, sans-serif;
font-size: 18px;
font-weight: bold;
}
.card__body .lambdaTest {
color: #fff;
}
/* MOBILE TABLETS */
@media all and (max-width: 1177px) {
.header {
grid-template-columns: repeat(2, 1fr);
}
}
/* MOBILE PHONES */
@media all and (max-width: 800px) {
.header {
grid-template-columns: repeat(1, 1fr);
}
}
Here, in the above CSS code, the @media (max-width: 1177px) targets screens with a maximum width of 1177px, such as tablets or smaller desktop screens. It adjusts the layout of the .header class element to have two columns, ensuring that content is displayed optimally and responsively on these devices.
Similarly, the @media (max-width: 800px) targets screens with a maximum width of 800px, typically smaller mobile devices. It adjusts the layout of the .header element to have a single column, allowing for better readability and usability on smaller screens. {% embed https://codepen.io/ocxigin/pen/rNbdNVj %} Desktop Result:
From a desktop point of view, the entire card is split into a three-column grid. This is the default styling for the card element. However, on a smaller screen, the card element will be split into smaller columns.
From the highlighted code above, the @media all and (max-width: 1177px); targets a viewport width of up to 1177px. This code specifies that the entire card element should be split into a two-column grid when the viewport width is 1177px or lower.
If you view this on a tablet device, you should see a two-column display grid.
On a tablet device, the card elements are split by a two-column grid to make the content accommodate the device. However, on mobile, we can make this even smaller to make the content fit into a mobile device.
From the above highlighted code, the @media all and (max-width: 800px): targets the device’s max-width at 800px. So when the device viewport width is exactly 800px or lower, that effect will occur.
Here, the card elements are split into a one-column grid, making it ideal for mobile phone display.
Mobile Result:
The max-width in media query can be very useful in cases where the desktop first approach is implemented. Then, the media query max-width can re-align the element with the specific breakpoint.
All the example results shown above are via LT Browser, a complementary tool LambdaTest offers.
LT Browser provides a comprehensive preview of your website across various devices. With 53+ device viewports, you can compare and synchronize interactions like scrolling and clicking. It is an all-in-one desktop application designed to help you optimize your website for responsive web design across all screens, viewports, and screen resolutions by performing live testing.
If you wish to use the LT Browser to test your website on different screen sizes and for responsiveness, download the LT Browser from the link below.
Watch the video tutorial below to become acquainted with LT Browser’s features and functionalities, including its pre-installed viewports for mobiles, tablets, desktops, and laptops.
As we have learned the core advantages of the mobile first CSS approach, in the below section, you will understand the difference between the mobile first CSS approach and responsive design.
Difference Between Mobile First CSS Approach and Responsive Web Design
Most people consider the mobile first CSS approach and responsive web design the same thing. Well, these are two different things, but they work hand-in-hand.
For example, the mobile first approach involves developing the mobile version of a website first and then progressively using breakpoint to re-style the website appearance for larger screens.
However, responsive web design, on the other hand, deals with creating a website that fits well across all mobile, tablet, laptop, and desktop devices, irrespective of the approach taken during development.
Responsive design does not favor any approach; however, it makes sure all websites fit well on any device that the website is loaded on to ensure maximum user experience.
Conclusion
The mobile first CSS approach prioritizes optimizing the user experience for mobile devices during website development. It involves using CSS container queries or media queries like min-width to set breakpoints for different viewport sections on larger screen sizes.
Implementing a mobile first CSS approach can significantly enhance the overall user experience and drive traffic, considering the high number of website visits from mobile devices. Adhering to the instructions outlined in the blog is crucial for successfully implementing the mobile first CSS approach.
Subscribe to my newsletter
Read articles from Alex Anie directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by