Analyzing the initial HTML structure and foundational CSS resets.
Before we can build complex components like forms or footers, we must first create a solid and reliable foundation for our web page. The goal of this first section is to understand the critical setup steps that every modern, responsive webpage requires.
We will analyze the initial HTML boilerplate, including the document
type declaration and the metadata within the
<head> tag. We will also examine the very first
rules in our CSS file, which are designed to "reset" inconsistent
browser defaults and establish a consistent, predictable visual
baseline for typography and colors across the entire application.
Our approach is "mobile-first," which means we'll start by styling for the smallest screen and then add complexity for larger screens. This is a best practice that leads to cleaner code and better performance.
The first part of our HTML file doesn't contain any visible elements. Instead, it's composed of metadata that provides essential instructions to the browser.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Login • Instagram</title>
<!-- Link to the external CSS file -->
<link rel="stylesheet" href="styles.css" />
<!-- Link to Font Awesome for the Facebook icon -->
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"
/>
</head>
<!DOCTYPE html>:
The Document Type Declaration. This is not an
HTML tag, but an instruction. It must be the very first line of
the file. It tells the browser that the document is written in
HTML5. Without this, browsers might enter "quirks mode," leading
to unpredictable and inconsistent rendering.
<html lang="en">:
The Root Element. This tag wraps all other
content on the page. The lang="en" attribute is
crucial for accessibility; it tells screen readers to use English
pronunciation rules and helps search engines correctly classify
the page's language.
<meta charset="UTF-8" />:
Character Encoding. This tag specifies the
character set for the page. UTF-8 is the universal standard that
supports all languages and symbols, including emojis. If this were
omitted, any text outside the basic English alphabet could appear
as garbled characters (e.g., "").
<meta name="viewport" ... />:
The Cornerstone of Responsiveness. This tag is
non-negotiable for any mobile-friendly site.
width=device-width forces the browser's viewport to
match the device's screen width, and
initial-scale=1.0 sets the default zoom level to
100%. Without this, a mobile browser would show a tiny, zoomed-out
version of the desktop layout.
<title>Login • Instagram</title>:
The Document Title. This sets the text that
appears in the browser tab, bookmarks, and search engine results.
It's vital for user experience and SEO.
<link rel="stylesheet" href="styles.css" />:
Linking Local CSS. This tag connects our HTML
document to our custom stylesheet, styles.css. The
browser will fetch this file and apply its rules to the HTML
elements.
<link rel="stylesheet" href="..." />:
Linking External CSS. This second link points to
a CDN (Content Delivery Network) for the Font Awesome icon
library. Using a CDN is often faster than hosting the file
yourself, as the user's browser may have already cached it from
visiting another site that uses the same CDN link. This gives us
access to icons like the Facebook logo without having to create
image files.
The first rules in a stylesheet are typically "resets" or "normalizers." They create a consistent starting point across all browsers, which all have slightly different default styles for elements.
/* General Body and Reset Styles */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
Arial, sans-serif;
background-color: #fafafa;
color: #262626;
margin: 0;
font-size: 14px;
line-height: 18px;
}
a {
text-decoration: none;
color: #00376b;
}
body { ... } selector: This targets
the main <body> element, and its styles are
inherited by most other elements on the page, establishing our
default look and feel.
font-family: ...;: This is a "font stack." The
browser tries to find and use each font in order, from left to
right. It starts with system-native fonts (-apple-system
for Safari, BlinkMacSystemFont for Chrome on macOS)
for optimal performance and a native feel. If none are found, it
falls back to common web-safe fonts ("Segoe UI",
Roboto, etc.) and finally to any generic
sans-serif font available.
background-color: #fafafa;: Sets a very light grey
background for the entire page, which is a subtle branding choice
that is less harsh than pure white.
color: #262626;: Sets the default text color to a
dark grey. Pure black (#000000) on a white background
can cause eye strain for some users; this softer color improves
readability.
margin: 0;: This is a critical reset. Browsers, by
default, add a small margin around the
<body> tag. This rule removes that margin,
ensuring our layout touches the very edge of the browser window
and giving us full control over spacing.
font-size: 14px; and line-height: 18px;:
These set the default size for our text and the vertical space
between lines of text, respectively. A line-height slightly larger
than the font size is essential for good readability.
a { ... } selector: This targets all
anchor (link) tags on the page.
text-decoration: none;: This removes the default
underline from all links, a common choice for modern web design.
color: #00376b;: This sets a custom dark blue color
for all links, making them visually distinct from regular text
while maintaining a consistent brand color.
Below is a live render of the code we've discussed in this section. Notice that there are no visible elements yet. However, the foundational styles are active. The page has a light grey background, and if there were any text or links, they would adopt the default font and colors we defined in the CSS. This is our blank canvas.
Analyzing the primary HTML structure and the core CSS Flexbox container that centers the page content.
With our foundational styles in place, we can now build the main structural skeleton of our page. The goal of this section is to understand how the highest-level containers in the HTML work together with CSS Flexbox to create a perfectly centered layout.
We will analyze the <main> element, which acts as
our primary layout controller. We will also introduce the two direct
children of this container: one for the phone image and one for the
form area. Understanding this parent-child structure is key to
grasping the responsive strategy, as we will be manipulating these
children at different screen sizes.
This block of HTML represents the highest-level visible structure of our page. It defines the main content area and its immediate children.
<body>
<main class="main-container">
<!-- This container holds the phone image, which is only visible on desktop -->
<div class="phones-container">
<img
class="phones-img"
src="./assets/images/app-demo.png"
alt="Two phones showing Instagram profiles"
/>
</div>
<!-- This container holds all the form-related content (to be documented next) -->
<!-- ... -->
</main>
</body>
<body>:
The Document Body. This tag contains all the
content that will be visually rendered in the browser window, such
as text, images, and links. It's the parent element for everything
the user sees.
<main class="main-container">:
The Main Content Wrapper. The
<main> tag is semantic HTML that signifies the
primary, unique content of the document. We've given it a class of
main-container, which we will use as a CSS selector
to turn this element into a powerful Flexbox container responsible
for the overall page layout.
<div class="phones-container">:
The Phone Image Container. This is the first of
two children inside our main container. Its sole purpose is to
hold the decorative phone image. Structuring it this way is a
critical architectural decision. It allows us to easily hide or
show this entire block of content at different screen sizes. The
comment above it is good practice, explaining its responsive
behavior to other developers.
<img class="phones-img" ... />:
The Phone Image. This is the actual image
element.
class="phones-img": A specific class for styling
the image itself (e.g., setting its height).
src="./assets/images/app-demo.png": The `src`
(source) attribute points to the location of the image file
relative to the HTML file.
alt="...": The `alt` (alternative text) attribute
is essential for accessibility. It provides a description of
the image for screen readers and is displayed if the image
fails to load.
These CSS rules directly correspond to the HTML structure we just defined. They use Flexbox to create the centered layout and implement the mobile-first strategy by hiding the phone image by default.
/* Main container for the entire page content */
.main-container {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
min-height: 80vh;
padding: 20px 0;
box-sizing: border-box;
}
/* Container for the phone image (hidden on mobile/tablet) */
.phones-container {
display: none; /* Hidden by default */
margin-right: 32px;
flex-shrink: 0; /* Prevents the image from shrinking */
}
.phones-img {
height: 580px;
}
.main-container { ... }: This rule
turns our main wrapper into a flexible centering machine.
display: flex;: This is the property that enables
Flexbox layout for the direct children of this element.
flex-direction: row;: This sets the main axis for
the flex items to be horizontal (left-to-right).
justify-content: center;: This centers the flex
items along the main (horizontal) axis.
align-items: center;: This centers the flex items
along the cross (vertical) axis.
min-height: 80vh;: This is vital for vertical
centering. It sets the container's height to be at least 80%
of the viewport's height, giving
align-items: center the vertical space it needs
to work.
padding: 20px 0;: Adds 20px of padding to the top
and bottom, preventing content from touching the screen edges.
box-sizing: border-box;: Ensures the padding is
calculated *inside* the element's total height, not added to
it.
.phones-container { ... }: This rule
controls the phone image's container.
display: none;: This is the
mobile-first implementation. By
default, we hide the phone container entirely. It is not just
invisible; it's removed from the document's render tree, so it
takes up no space.
margin-right: 32px;: This rule currently does
nothing because the element is hidden. However, it's
pre-written for when we show the element on desktop screens,
where it will create a 32px gap between the phone image and
the form.
flex-shrink: 0;: This is another forward-thinking
rule. When the element is visible in a flex container, this
prevents it from shrinking if the container runs out of space.
It ensures the image always maintains its intended size.
.phones-img { ... }:
height: 580px;: This sets a fixed height for the
image. The browser will automatically calculate the width to
maintain the image's original aspect ratio.
Below is a live render of the code we've discussed. To help you
visualize the layout, the .phones-container has been made
visible for this demo (by overriding display: none with
display: block). You can see how the
.main-container's Flexbox properties perfectly center the
phone image both vertically and horizontally within the available
space. This centering behavior is the foundation upon which the rest
of our page will be built.
Analyzing the structure of the form's containers and the main "card" that holds the login elements.
Now that we have our main page container, our goal is to build the primary interactive area of the page. This section focuses on the containers that create the distinct white boxes, or "cards," for logging in, signing up, and getting the app.
We will analyze the form-area-container, which acts as a
wrapper for all these boxes. Then, we'll dive into the first and most
important box, the login-box. We will examine how it's
structured to hold the Instagram logo and the main login form, and how
its corresponding CSS creates the visual appearance of a
self-contained card.
This block of HTML is nested inside the main-container.
It defines the wrapper for all form-related content and the structure
of the first box, which contains the logo and the form itself.
<!-- This container holds all the form-related content -->
<div class="form-area-container">
<!-- The main login form box -->
<div class="form-box login-box">
<div class="logo-container">
<img
class="instagram-logo"
src="assets/images/Instagram_logo.png"
/>
</div>
<form class="login-form">
<!-- Form inputs will be documented next -->
</form>
<!-- ... Rest of the login box content -->
</div>
<!-- ... Other form boxes -->
</div>
<div class="form-area-container">:
The Form Group Wrapper. This `div` acts as a
wrapper and a Flexbox container for the three distinct boxes
(login, signup, get the app) together. Its purpose is to group the
three distinct boxes (login, signup, get the app) together. We
will use CSS to make this a column-based flex container, ensuring
the boxes stack vertically.
<div class="form-box login-box">:
The Login Card. This is a crucial element with
two classes.
form-box: This is a
shared, presentational class.
As we'll see later, the "signup" box also uses this class.
This allows us to apply common styles (like the white
background, padding, and eventually a border) to both boxes
from a single CSS rule, following the DRY (Don't Repeat
Yourself) principle.
login-box: This is a
specific, identifying class. It
can be used to apply styles that are unique *only* to the
login box.
<div class="logo-container">:
Logo Wrapper. While we could have placed the logo
image directly in the login box, wrapping it in its own `div`
gives us more precise control over its spacing, such as the margin
above and below it, without affecting other elements.
<img class="instagram-logo" ... />: The actual
logo image. We give it a class so we can control its dimensions
(height and width) directly in the CSS.
<form class="login-form">:
The Semantic Form Element. Using the
<form> tag is semantically correct and
important for accessibility and browser functionality. It tells
the browser that the elements inside are part of an interactive
form. The login-form class will be used to style the
layout of the inputs and button within it.
These CSS rules define the layout of the form area and create the visual appearance of the login box card.
/* Container for the form elements */
.form-area-container {
display: flex;
flex-direction: column;
justify-content: center;
max-width: 350px;
width: 100%;
}
/* Shared styles for the login and signup boxes */
.form-box {
background-color: #ffffff;
text-align: center;
padding: 10px 0;
margin-bottom: 10px;
}
.logo-container {
margin: 22px auto 12px;
}
.logo {
height: 51px;
width: 175px;
}
/* Form input and button styling */
.login-form {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 40px;
}
.form-area-container { ... }:
display: flex; flex-direction: column;: This
turns the container into a Flexbox container but sets its main
axis to be vertical. This ensures its children (the login box,
signup box, etc.) will stack on top of each other.
justify-content: center;: Centers the stacked
boxes vertically within the container.
max-width: 350px;: This is a key constraint. It
prevents the form area from becoming excessively wide on large
screens.
width: 100%;: This makes the container
responsive. It will try to be 350px wide, but on screens
narrower than 350px, it will shrink to fit, occupying 100% of
the available width.
.form-box { ... }: This styles our
reusable "card" component.
background-color: #ffffff;: Sets the card's
background to pure white, making it stand out against the
light grey page background.
text-align: center;: Centers the text and other
inline content (like the logo) within the box.
padding: 10px 0;: Adds 10px of padding to the top
and bottom of the box.
margin-bottom: 10px;: Creates a 10px gap between
this box and the next one below it (the signup box).
.logo-container and .logo:
margin: 22px auto 12px;: This is a shorthand for
setting margins. It applies 22px to the top, 12px to the
bottom, and `auto` to the left and right. Using `auto` for
left/right margins on a block element is a classic technique
to horizontally center it within its parent.
height: 51px; width: 175px;: These rules give the
logo image explicit dimensions.
.login-form { ... }:
display: flex; flex-direction: column;: Just like
the container above, this makes the form a vertical flex
container, ensuring the input fields and button will stack
vertically.
align-items: center;: Since the direction is
`column`, `align-items` now controls horizontal alignment,
centering the items within the form.
padding: 0 40px;: Adds 40px of padding to the
left and right of the form, preventing the input fields from
touching the edges of the card.
Below is a live render of the code we've discussed. You can now see
the form-area-container, which is constrained to a
maximum width of 350px and is centered on the page. Inside it, the
white form-box is visible, containing the centered
Instagram logo. This structure forms the main card element of our
login page, ready for us to add the input fields.
Analyzing the core interactive elements of the form: the input fields and the submit button.
With the main structure of our login card in place, our goal is now to populate it with the essential interactive elements that allow a user to log in. This is the heart of the form's functionality.
In this section, we will dissect the HTML for the username and
password input fields, as well as the "Log in" button. We will pay
close attention to the attributes used for accessibility and browser
behavior. In the CSS, we will analyze how these elements are styled to
be visually appealing, user-friendly, and consistent with Instagram's
design, including their appearance during user interaction (the
:focus state).
This block of HTML is nested inside the
<form class="login-form"> element. It defines the
two text fields and the primary submission button.
<div class="input-wrapper">
<input
type="text"
id="username"
name="username"
aria-label="Phone number, username, or email"
placeholder="Phone number, username, or email"
required
/>
</div>
<div class="input-wrapper">
<input
type="password"
id="password"
name="password"
aria-label="Password"
placeholder="Password"
required
/>
</div>
<button type="submit" class="login-button">Log in</button>
<div class="input-wrapper">:
The Input Wrapper. Each
<input> is wrapped in this `div`. This is a
common and useful pattern. It allows us to control the spacing
between the input fields (using `margin` on the wrapper) without
having to apply margins directly to the inputs themselves, which
can sometimes interfere with other layout properties.
<input ... />:
The Input Field.
type="text" / type="password": This
attribute is crucial. text creates a standard
text field. password creates a field where the
typed characters are obscured (e.g., shown as dots), which is
essential for security.
id="username": The `id` is a unique identifier
for this specific element. It's commonly used to link a
<label> to an input (for accessibility) and
to select the element with JavaScript.
name="username": The `name` attribute is used
when the form is submitted. The data from this input will be
sent to the server as a key-value pair, like
`username=users_entry`.
aria-label="...": Since we have no visible
<label> text on the screen, this
accessibility attribute provides a description of the input's
purpose for screen readers.
placeholder="...": This provides the grey hint
text that appears inside the field before the user types
anything. It's a visual cue, not a replacement for a proper
label.
required: This is an HTML5 validation attribute.
It tells the browser that this field cannot be empty when the
form is submitted. If it is, the browser will prevent
submission and show a warning.
<button type="submit" ...>:
The Submit Button.
<button> tag is the standard for
creating clickable buttons.
type="submit": This is the default behavior for a
button inside a <form>, but it's good
practice to be explicit. It tells the browser that clicking
this button should trigger the form's submission process.
These CSS rules give the inputs and button their distinctive Instagram look and feel, including interactive states.
.input-wrapper {
width: 100%;
margin-bottom: 6px;
}
.login-form input {
width: 100%;
padding: 9px 8px 7px;
background-color: #fafafa;
border: 1px solid #dbdbdb;
border-radius: 3px;
box-sizing: border-box;
font-size: 12px;
}
.login-form input:focus {
outline: none;
border-color: #a8a8a8;
}
.login-button {
width: 100%;
padding: 8px;
margin: 8px 0;
background-color: #0095f6;
color: white;
border: none;
border-radius: 8px;
font-weight: bold;
cursor: pointer;
}
.login-button:disabled {
background-color: #b2dffc;
cursor: default;
}
.input-wrapper { ... }:
width: 100%;: Ensures the wrapper takes up the
full width of its parent (the padded area of the form).
margin-bottom: 6px;: Creates a small, consistent
vertical gap between the input fields.
.login-form input { ... }:
width: 100%;: Makes the input field itself fill
the entire width of its wrapper.
padding: 9px 8px 7px;: Adds internal spacing
inside the input field for the text.
background-color: #fafafa; &
border: 1px solid #dbdbdb;: Styles the input with
a very light grey background and a thin border to match the
page aesthetic.
border-radius: 3px;: Gives the input fields
slightly rounded corners.
box-sizing: border-box;: This is a critical rule.
It ensures that the padding and
border are included *within* the `width: 100%`
calculation, preventing the inputs from overflowing their
container.
.login-form input:focus { ... }:
This is a pseudo-class that applies styles only when the user has
clicked into an input field.
outline: none;: Removes the default, often thick
and blue, outline that browsers add to focused elements.
border-color: #a8a8a8;: As a replacement for the
outline, we make the border slightly darker. This provides a
clean, subtle, and branded visual cue that the element is
active.
.login-button { ... }:
background-color: #0095f6; &
color: white;: Sets the iconic blue background
and white text.
border: none;: Removes the default browser border
from the button.
border-radius: 8px;: Gives the button more
prominently rounded corners than the inputs.
font-weight: bold;: Makes the button text bold to
give it emphasis.
cursor: pointer;: Changes the mouse cursor to a
pointing hand when hovering over the button, clearly
indicating it's clickable.
.login-button:disabled { ... }: This
pseudo-class styles the button only when it has a `disabled` HTML
attribute.
background-color: #b2dffc;: Changes the
background to a faded, light blue.
cursor: default;: Changes the cursor back to the
default arrow. Together, these rules provide clear visual
feedback that the button is currently inactive.
Below is a live render of our progress. The login card now contains
the fully styled username and password fields, along with the vibrant
blue "Log in" button. You can click into the input fields to see the
:focus style in action, where the border becomes slightly
darker. This represents the core interactive component of our page.
Analyzing the "OR" separator and alternative login options like "Log in with Facebook".
After establishing the primary login method, modern user interfaces often provide alternative options. The goal of this section is to understand how to create the visual elements that separate the main form from these secondary actions.
We will first dissect the "OR" separator, a common UI pattern that visually divides content sections. We'll focus on the clever use of CSS Flexbox to create the responsive lines on either side of the text. Following that, we will analyze the "Log in with Facebook" button and the "Forgot password?" link, examining how they are structured in HTML and styled with CSS to be clear, accessible, and distinct calls to action.
This block of HTML is located inside the .login-box,
immediately following the <form> element. It
defines the visual separator and the alternative action links.
<div class="separator">
<div class="line"></div>
<div class="or-text">OR</div>
<div class="line"></div>
</div>
<div class="social-login">
<button class="facebook-login">
<i class="fab fa-facebook-square"></i>
<span>Log in with Facebook</span>
</button>
</div>
<a href="#" class="forgot-password">Forgot password?</a>
<div class="separator">:
The Separator Container. This `div` acts as a
wrapper and a Flexbox container for the three elements inside it:
two lines and the "OR" text.
<div class="line"></div>:
The Separator Lines. These are empty `div`
elements. They have no content themselves; their entire visual
appearance—a horizontal line—will be created purely with CSS (by
giving them a height and a background color). We use two separate
divs to have one on each side of the text.
<div class="or-text">OR</div>:
The "OR" Text. This simply holds the text content
"OR". Wrapping it in a `div` allows us to control its spacing
(margins) independently of the lines.
<div class="social-login">:
Social Login Wrapper. This container groups all
social login buttons (in this case, just one) for styling and
spacing purposes.
<button class="facebook-login">:
The Facebook Login Button. We use a
<button> for semantic correctness, as it
represents a clickable action.
<i class="fab fa-facebook-square"></i>:
The Facebook Icon. This is an element from the
Font Awesome library we linked in Part 1. The classes
fab (Font Awesome Brands) and
fa-facebook-square tell the library to render the
square Facebook logo icon here.
<span>Log in with Facebook</span>: The
text part of the button is wrapped in a <span>.
This isn't strictly necessary but can be useful if we wanted to
style the text separately from the icon.
<a href="#" class="forgot-password">...</a>: The "Forgot Password" Link. This is a standard
anchor (link) tag. The href="#" is a placeholder that
makes it behave like a link without navigating anywhere.
These CSS rules are responsible for the clever layout of the "OR" separator and the distinct styling of the social login options.
/* "OR" separator styling */
.separator {
display: flex;
align-items: center;
margin: 10px 40px 18px;
color: #8e8e8e;
font-weight: 600;
font-size: 13px;
}
.line {
flex-grow: 1;
height: 1px;
background-color: #dbdbdb;
}
.or-text {
margin: 0 18px;
}
/* Social login and other links */
.social-login {
margin-bottom: 10px;
}
.facebook-login {
background: none;
border: none;
color: #385185;
font-weight: 600;
font-size: 14px;
cursor: pointer;
padding: 0;
}
.facebook-login i {
font-size: 16px;
margin-right: 8px;
}
.forgot-password {
font-size: 12px;
color: #00376b;
margin-top: 12px;
display: inline-block;
}
.separator { ... }:
display: flex;: This turns the separator into a
flex container, placing the two lines and the text in a row.
align-items: center;: This vertically aligns the
items in the center, ensuring the 1px-tall lines are perfectly
aligned with the middle of the "OR" text.
margin: 10px 40px 18px;: This sets the spacing
around the separator: 10px on top, 40px on the left/right, and
18px on the bottom.
.line { ... }: This is the most
clever part of the component.
flex-grow: 1;: This property is the key. It tells
the flex items (the two lines) to "grow" and take up any
available free space within the flex container. Since both
lines have flex-grow: 1, they share the available
space equally. This means they will automatically stretch to
fill the container, no matter how wide it is.
height: 1px; &
background-color: #dbdbdb;: These two properties
create the visual appearance of the line itself.
.or-text { ... }:
margin: 0 18px;: This creates space on the left
and right of the "OR" text, preventing the lines from touching
it.
.facebook-login { ... }:
background: none; border: none;: These rules
remove the default browser styling for a button, making it
look like plain text.
color: #385185;: Sets the text color to
Facebook's brand blue.
font-weight: 600;: Makes the text semi-bold.
.facebook-login i { ... }:
<i>) specifically.
margin-right: 8px; adds a small gap between the
icon and the text next to it.
.forgot-password { ... }:
display: inline-block;: This is important. By
default, an anchor tag is `inline`. Setting it to
`inline-block` allows us to apply top and bottom margins,
which we do with `margin-top: 12px;` to create space between
it and the Facebook button above.
Below is a live render of the components discussed. You can see the "OR" separator, which will responsively stretch to fill the width of its container. Below it are the distinctly styled "Log in with Facebook" button and the "Forgot password?" link, providing clear secondary actions for the user.
Analyzing the "Sign up" prompt and the "Get the app" section.
Beyond the primary login functionality, a successful login page often includes secondary calls to action designed to onboard new users or drive engagement with other platforms. The goal of this section is to analyze these crucial marketing and user-acquisition components.
We will dissect the "Sign up" box, which provides a clear pathway for new users. We'll focus on how it reuses existing CSS classes for consistency. We will then examine the "Get the app" section, analyzing how it presents download links for mobile app stores and how Flexbox is used to create a clean, centered layout for the store badges.
This block of HTML is located inside the
.form-area-container, immediately following the main
.login-box. It defines the next two visual blocks in our
vertical column.
<!-- The box for signing up -->
<div class="form-box signup-box">
<p>
Don't have an account? <a href="#" class="signup-link">Sign up</a>
</p>
</div>
<!-- The section for app download links -->
<div class="get-the-app">
<p>Get the app.</p>
<div class="app-store-links">
<a href="#">
<img
src="https://static.cdninstagram.com/rsrc.php/v3/yz/r/c5Rp7Ym-Klz.png"
alt="Download on the App Store"
/>
</a>
<a href="#">
<img
src="https://static.cdninstagram.com/rsrc.php/v3/yu/r/EHY6QnZYdNX.png"
alt="Get it on Google Play"
/>
</a>
</div>
</div>
<div class="form-box signup-box">:
The Signup Card. This demonstrates the power of
reusable classes.
form-box class from the login
section, this `div` automatically inherits the white
background, padding, and bottom margin, ensuring it looks
visually consistent with the box above it.
signup-box class is available for any
specific styling unique to this box, although none is needed
in this implementation.
<p>...</p>: A paragraph tag holds the
text content.
<a href="#" class="signup-link">Sign up</a>: The Signup Link. This is a standard anchor tag
that would navigate to the registration page. The
signup-link class will be used to give it a distinct,
clickable appearance.
<div class="get-the-app">:
App Section Container. This `div` wraps the "Get
the app" prompt and the store links, separating them logically
from the form boxes above.
<div class="app-store-links">:
Store Links Wrapper. This container holds the two
app store images. We will use this class to turn it into a Flexbox
container to easily align the two images side-by-side.
<a href="#"><img ... /></a>:
Clickable Store Badges. Each store badge is an
image wrapped in an anchor tag. This makes the entire image a
clickable link, which is standard practice for app store buttons.
The alt text is crucial for accessibility, describing
the link's destination (e.g., "Download on the App Store").
These CSS rules style the signup link and create the centered layout for the app store badges.
/* Signup box styling */
.signup-box p {
margin: 15px;
}
.signup-link {
font-weight: 600;
color: #0095f6;
}
/* "Get the app" section styling */
.get-the-app {
text-align: center;
}
.get-the-app p {
margin: 20px 0;
}
.app-store-links {
display: flex;
justify-content: center;
gap: 8px;
}
.app-store-links img {
height: 40px;
}
.signup-box p { ... }:
margin: 15px;: This rule targets the paragraph
inside the signup box and gives it a 15px margin on all sides,
ensuring the text doesn't touch the edges of the card.
.signup-link { ... }:
font-weight: 600;: Makes the link text semi-bold,
drawing more attention to it.
color: #0095f6;: Sets the color to the bright,
clickable blue used for the main login button, creating a
consistent visual language for primary actions.
.get-the-app { ... }:
text-align: center;: This centers the "Get the
app." paragraph text within the container.
.get-the-app p { ... }:
margin: 20px 0;: Adds 20px of space above and
below the paragraph, separating it from the signup box above
and the store links below.
.app-store-links { ... }:
display: flex;: Turns the container into a
flexbox, placing the two store badge links side-by-side.
justify-content: center;: Centers the two badges
horizontally within the available space.
gap: 8px;: The gap property is a
modern and convenient way to create space *between* flex
items. This adds an 8px gap between the two store badges
without having to use margins.
.app-store-links img { ... }:
height: 40px;: Sets a fixed height for the app
store badge images, ensuring they are displayed at a
consistent and appropriate size.
Below is a live render of the components discussed in this section. You can see the "Sign up" box, which is visually consistent with the login box from previous sections. Below that is the "Get the app" section, featuring the centered app store badges with a clean gap between them.
Analyzing the structure and responsive styling of the footer links and copyright information.
While the main content of a page gets the most attention, a well-structured footer is essential for providing users with important secondary navigation, legal information, and other resources. The goal of this section is to understand how to build a clean, multi-part, and responsive footer.
We will dissect the HTML structure of the entire
<footer> element, including the container for the
main list of links and the separate container for the language
selector and copyright notice. In the CSS, we will focus on how
Flexbox is used with the flex-wrap property to allow the
list of links to adapt gracefully to different screen sizes,
preventing overflow and maintaining readability.
This block of HTML is the last major element in the
<body>. It defines the entire footer section of the
page.
<footer class="page-footer">
<div class="footer-container">
<div class="footer-links">
<a href="#">Meta</a>
<a href="#">About</a>
<a href="#">Blog</a>
<a href="#">Jobs</a>
<a href="#">Help</a>
<a href="#">API</a>
<a href="#">Privacy</a>
<a href="#">Terms</a>
<a href="#">Locations</a>
<a href="#">Instagram Lite</a>
<a href="#">Threads</a>
<a href="#">Contact Uploading & Non-Users</a>
<a href="#">Meta Verified</a>
</div>
<div class="footer-bottom">
<div class="language-select">
<span>English</span>
<i class="fas fa-chevron-down"></i>
</div>
<div class="copyright">© 2024 Instagram from Meta</div>
</div>
</div>
</footer>
<footer class="page-footer">:
The Footer Element. Using the semantic
<footer> tag clearly defines this section's
purpose for browsers and assistive technologies. The
page-footer class is our selector for styling.
<div class="footer-container">:
An Inner Wrapper. This extra container inside the
footer is used to group the links and the bottom section. This can
be useful for applying certain layout or positioning styles that
affect the entire group, as we'll see in the media queries later.
<div class="footer-links">:
The Links Container. This `div` wraps the entire
list of navigation links. Its primary purpose is to act as a
Flexbox container, which will allow the links to wrap onto
multiple lines on smaller screens.
<a href="#">...</a>:
Footer Navigation Links. Each of these is a
standard anchor tag providing navigation to other pages.
<div class="footer-bottom">:
Bottom Section Wrapper. This container groups the
language selector and the copyright notice, keeping them together
and allowing them to be styled as a single unit.
<div class="language-select">: A container for
the language selection UI.
<i class="fas fa-chevron-down"></i>: A
Font Awesome icon that renders a small downward-facing chevron,
indicating a dropdown menu.
<div class="copyright">©
2024...</div>: The copyright notice. The © is an HTML
entity that reliably renders the copyright symbol (©).
These CSS rules handle the layout and appearance of the footer, with a key focus on the responsive behavior of the link list.
/* Footer styling */
.page-footer {
padding: 0 16px;
text-align: center;
color: #8e8e8e;
font-size: 12px;
}
.footer-links {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 8px 16px;
margin-bottom: 12px;
}
.footer-links a {
color: #8e8e8e;
}
.footer-bottom {
display: flex;
justify-content: center;
gap: 16px;
margin-bottom: 52px;
}
.language-select {
cursor: pointer;
}
.language-select i {
font-size: 10px;
margin-left: 4px;
}
.page-footer { ... }:
padding: 0 16px;: Adds 16px of padding on the
left and right, ensuring the footer content doesn't touch the
screen edges on mobile.
text-align: center;: Centers all the text content
within the footer by default.
color: #8e8e8e; font-size: 12px;: Sets a smaller,
grey font style for the footer text, indicating its secondary
importance.
.footer-links { ... }: This is the
most important ruleset for the footer's responsiveness.
display: flex;: Turns the container into a
flexbox.
flex-wrap: wrap;: This is the key property. By
default, flex items try to stay on one line.
wrap allows them to break onto a new line if they
run out of space. This is what makes the list of links shrink
from one long line on desktop to multiple shorter lines on
mobile.
justify-content: center;: Centers the links
horizontally on each line.
gap: 8px 16px;: This sets the gap between flex
items. The first value (8px) is the row-gap
(vertical space between lines of links), and the second value
(16px) is the column-gap (horizontal space
between links on the same line).
.footer-links a { ... }:
color: #8e8e8e;: Ensures the links inside this
container have the same grey color as the rest of the footer
text, overriding the default blue link color we set in Part 1.
.footer-bottom { ... }:
display: flex; justify-content: center;: This
turns the bottom section into a centered flex container,
placing the language selector and copyright side-by-side.
gap: 16px;: Adds a 16px space between the
language selector and the copyright notice.
margin-bottom: 52px;: Adds a large amount of
space at the very bottom of the page for visual balance.
Below is a live render of the complete footer component. Try resizing
the window or the preview pane. You will see the list of links
automatically "wrap" onto multiple lines as the available width
decreases. This is the power of the
flex-wrap: wrap property in action, creating a fully
responsive component with very little code.
Analyzing the first media query and the transition from a mobile to a tablet layout.
Up to this point, all our styles have been "mobile-first," meaning they apply to all screen sizes. Now, we introduce our first responsive change. The goal of this section is to understand how to use a CSS media query to apply specific styles only when the screen reaches a certain minimum width, effectively creating a distinct "tablet" layout.
We will analyze the @media (min-width: 450px) rule, which
acts as a conditional wrapper for our tablet styles. The key visual
change we'll implement is adding a border to the form "cards," making
them stand out against the page background, which is more appropriate
for larger screens. We'll also examine how spacing and positioning are
adjusted to better suit a wider viewport.
For this part of our documentation, there are no changes to the
login-page.html file. This is a critical concept to
understand:
media queries do not change the HTML structure. Instead, they selectively apply different CSS rules to the
*existing* HTML based on the viewport's characteristics. Our
well-structured HTML from the previous parts is already prepared to
handle these new styles.
This block of CSS is our first foray into responsive design. The
@media rule tells the browser to only apply the styles
inside it if the viewport width is 450 pixels or greater.
/* -------------------- MEDIA QUERIES -------------------- */
/* Tablet Styles (and above) */
@media (min-width: 450px) {
body {
background-color: #fafafa; /* Ensures background is consistent */
}
.main-container {
padding: 40px; /* Add some padding */
}
.form-box {
border: 1px solid #dbdbdb;
border-radius: 1px;
}
.form-area-container {
/* On tablet, the form area is centered horizontally */
margin: 0 auto;
}
.footer-container {
position: absolute;
bottom: -140px;
}
.page-footer {
width: 100%;
position: relative;
padding-bottom: 20px;
}
}
@media (min-width: 450px) { ... }:
This is the media query rule.
@media: The keyword that initiates the rule.
(min-width: 450px): This is the "media feature"
or condition. It translates to: "If the viewport width is a
minimum of 450px (i.e., 450px or wider), then apply the CSS
rules inside this block." On any screen narrower than 450px,
the browser will completely ignore these rules.
body { ... }:
background-color: #fafafa;: While we already set
this in the base styles, explicitly setting it again inside
the media query ensures that the light grey background is
visible. On a very narrow mobile screen, the form area might
take up the full width, hiding the body's background. This
rule guarantees it's seen on wider screens.
.main-container { ... }:
padding: 40px;: This increases the padding around
the main content area, giving it more "breathing room" on a
larger tablet screen compared to the tighter mobile layout.
.form-box { ... }: This is the most
significant visual change in this breakpoint.
border: 1px solid #dbdbdb;: This adds a thin,
light grey border around our .form-box elements
(the login and signup cards). This visually separates the
white cards from the grey page background, a classic design
pattern for tablet and desktop views.
border-radius: 1px;: Applies a very subtle
rounding to the corners of the new border.
.form-area-container { ... }:
margin: 0 auto;: This is a classic CSS centering
technique. When applied to a block-level element that has a
defined width (like our .form-area-container with
its `max-width: 350px`), it automatically calculates equal
margins for the left and right, perfectly centering the
element horizontally.
.footer-container { ... } and
.page-footer { ... }:
position: absolute; and
position: relative;: These rules introduce more
advanced positioning. By making the
.page-footer `relative`, it becomes a positioning
context for its children. Making the inner
.footer-container `absolute` removes it from the
normal document flow and positions it relative to its parent.
bottom: -140px; then pushes it 140px below the
bottom edge of the .page-footer. This is a
specific technique used here to manage footer placement at
this particular breakpoint.
Below is a live render of our page with the tablet media query applied. The preview pane is resizable. Drag its right edge to change the width.
Analyzing the final media query and the "magic switch" that creates the two-column desktop layout.
This is the final and most dramatic step in our responsive journey. The goal of this section is to understand how the second media query, targeting desktop screens, transforms our single-column layout into the iconic two-column Instagram login page.
We will analyze the @media (min-width: 875px) rule. The
primary focus will be on the single most important line of code in our
responsive strategy: the rule that changes the
display property of the phone container from
none to block. We'll explore in detail how
this "magic switch" interacts with our existing Flexbox setup to bring
the hidden phone image into view and create the final desktop design.
We will also cover the minor layout adjustments that polish this final
view.
Once again, no changes are needed for the
login-page.html file. The power of our mobile-first
approach and well-structured HTML is that the same document structure
can support all three layouts (mobile, tablet, and desktop) without
any modification. The transformation is handled entirely by the CSS.
This block of CSS activates only on screens 875px or wider. It contains the rules that override our mobile and tablet styles to create the final desktop layout.
/* Desktop Styles */
@media (min-width: 875px) {
.main-container {
/* Re-center content for two-column layout */
justify-content: center;
align-items: center;
min-height: 90vh;
padding-top: 20px; /* Reset padding */
}
.phones-container {
display: block; /* Show the phone image */
}
.form-area-container {
margin: 0; /* Reset margin */
}
.footer-container {
position: static;
}
.page-footer {
max-width: 935px;
margin: 0 auto;
}
}
@media (min-width: 875px) { ... }:
This media query creates the desktop breakpoint. The value of
875px was chosen as a width that can comfortably accommodate the
phone image (which has a fixed height and thus an implicit width)
next to the 350px-wide form area, with a pleasant margin between
them.
.main-container { ... }:
justify-content: center and
align-items: center were already present in the
base styles, redefining them here ensures they apply correctly
to the new two-column context, centering the entire
phone-and-form group on the page.
.phones-container { ... }: This is
the most important rule in the entire file.
display: block;: This is the
"magic switch." In our
mobile-first base styles (Part 2), this container was set to
display: none;, completely removing it from the
page. This rule overrides that base style. By changing the
display property to block, the browser is
instructed to render the phone container. Because its parent
(.main-container) is a flex container with
flex-direction: row, it automatically appears as
a column to the left of its sibling, the
.form-area-container.
.form-area-container { ... }:
margin: 0;: In the tablet breakpoint (Part 8), we
added margin: 0 auto; to center the form
container. Now that it's a flex item sitting next to the phone
image, we no longer need that auto margin. This rule resets
the margin to zero.
.footer-container { ... }:
position: static;: In the tablet styles, we set
the footer to position: absolute. This rule
resets it back to static, the default
positioning, so it sits naturally at the bottom of the content
flow again.
.page-footer { ... }:
max-width: 935px; margin: 0 auto;: This rule
constrains the width of the footer and centers it. This
prevents the footer links from stretching to the full width of
a very wide monitor, which would look awkward and be hard to
read.
Below is a live render of the complete, fully responsive page. The preview pane is resizable. Drag its right edge to see all three layouts in action.
And with that, the implementation is complete.
Below is a live render of the complete, final login page. It incorporates all the HTML and CSS we have documented across all 10 parts. This is the finished product, fully responsive and functional. Use this final preview to explore the complete application and see how every component we've discussed comes together to form a cohesive whole.
Across these 10 parts, we have systematically deconstructed a professional, fully responsive login page. By examining the HTML and CSS in discrete sections, we have illuminated the core pillars of modern front-end web development.
<main>, <footer>, and
<form> provides inherent meaning, which is
crucial for assistive technologies and search engines. A
well-planned structure made the subsequent CSS styling far
simpler.
justify-content,
align-items, flex-wrap, and
flex-grow is essential for modern CSS.
display: none to
display: block to fundamentally alter the layout
for desktop, demonstrating that responsive design is about
conditionally changing how elements participate in the document
flow.
By understanding and applying these core principles, you are now equipped to move beyond simply copying code and can begin to architect your own robust, professional, and truly responsive web experiences from the ground up.