Tutorial css
CSS Responsive Design
Responsive Design adalah pendekatan design yang membuat website menyesuaikan dengan berbagai ukuran layar dan device. Website responsive memberikan user experience yang optimal di desktop, tablet, dan mobile.
Mengapa Responsive Design Penting?
Statistik Mobile Usage
- 54%+ traffic internet dari mobile
- Google prioritas mobile-first indexing
- User expectation website harus mobile-friendly
- Better SEO ranking untuk responsive sites
Keuntungan Responsive
✅ Satu website untuk semua device
✅ Lower maintenance cost
✅ Better SEO performance
✅ Improved user experience
✅ Future-proof design
Mobile-First Approach
Konsep Mobile-First
/* ✅ Mobile First (Recommended) */
.container {
padding: 1rem; /* Mobile base */
}
@media (min-width: 768px) {
.container {
padding: 2rem; /* Tablet */
}
}
@media (min-width: 1024px) {
.container {
padding: 3rem; /* Desktop */
}
}
/* ❌ Desktop First (Avoid) */
.container {
padding: 3rem; /* Desktop base */
}
@media (max-width: 1023px) {
.container {
padding: 2rem; /* Tablet */
}
}
@media (max-width: 767px) {
.container {
padding: 1rem; /* Mobile */
}
}
Viewport Meta Tag
<!DOCTYPE html>
<html>
<head>
<!-- WAJIB untuk responsive design -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Optional viewport settings -->
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes"
/>
</head>
<body>
<!-- Content -->
</body>
</html>
Viewport Properties
width=device-width
- Gunakan lebar deviceinitial-scale=1.0
- Zoom level awalmaximum-scale=5.0
- Zoom maksimaluser-scalable=yes
- Allow zoom (accessibility)
Media Queries
Breakpoint Standard
/* Common Breakpoints */
:root {
--mobile: 320px;
--tablet: 768px;
--desktop: 1024px;
--large: 1440px;
--extra-large: 1920px;
}
/* Mobile First Media Queries */
@media (min-width: 480px) {
/* Large mobile */
}
@media (min-width: 768px) {
/* Tablet */
}
@media (min-width: 1024px) {
/* Desktop */
}
@media (min-width: 1440px) {
/* Large desktop */
}
Media Query Syntax
/* Basic media query */
@media screen and (min-width: 768px) {
.container {
max-width: 1200px;
}
}
/* Multiple conditions */
@media screen and (min-width: 768px) and (max-width: 1023px) {
.tablet-only {
display: block;
}
}
/* Orientation */
@media (orientation: landscape) {
.landscape-layout {
flex-direction: row;
}
}
@media (orientation: portrait) {
.portrait-layout {
flex-direction: column;
}
}
/* High resolution displays */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
.high-res-image {
background-image: url("image@2x.jpg");
}
}
Fluid Layouts
Percentage-based Widths
.fluid-container {
width: 100%; /* Full width */
max-width: 1200px; /* Maximum width */
margin: 0 auto; /* Center horizontally */
padding: 0 20px; /* Horizontal padding */
}
.fluid-columns {
display: flex;
gap: 2rem;
}
.main-content {
flex: 2; /* 2/3 width */
}
.sidebar {
flex: 1; /* 1/3 width */
}
CSS Grid Fluid
.fluid-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
padding: 2rem;
}
.responsive-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
gap: clamp(1rem, 3vw, 2rem);
}
Flexible Units
Relative Units
/* Viewport units */
.hero-section {
height: 100vh; /* Full viewport height */
width: 100vw; /* Full viewport width */
}
.responsive-text {
font-size: 4vw; /* 4% of viewport width */
max-font-size: 2rem; /* Maximum size */
min-font-size: 1rem; /* Minimum size */
}
/* Container-relative units (modern) */
.container-relative {
font-size: 3cqw; /* 3% of container width */
padding: 2cqh; /* 2% of container height */
}
/* Relative to font size */
.em-units {
padding: 1em; /* Relative to element font-size */
margin: 1rem; /* Relative to root font-size */
}
Clamp Function
.responsive-spacing {
/* clamp(minimum, preferred, maximum) */
padding: clamp(1rem, 5vw, 3rem);
font-size: clamp(1rem, 2.5vw, 2rem);
gap: clamp(1rem, 3vw, 2rem);
}
.responsive-width {
width: clamp(300px, 80vw, 1200px);
margin: 0 auto;
}
Min/Max Functions
.flexible-sizing {
width: min(90vw, 1200px); /* Whichever is smaller */
height: max(300px, 50vh); /* Whichever is larger */
font-size: min(max(1rem, 4vw), 2rem); /* Nested functions */
}
Responsive Images
Basic Responsive Images
.responsive-image {
max-width: 100%; /* Never exceed container */
height: auto; /* Maintain aspect ratio */
display: block; /* Remove inline spacing */
}
.hero-image {
width: 100%;
height: 50vh;
object-fit: cover; /* Cover container */
object-position: center; /* Center focus point */
}
Art Direction with Picture Element
<picture>
<!-- Large screens: landscape image -->
<source media="(min-width: 1024px)" srcset="hero-landscape.jpg" />
<!-- Medium screens: square image -->
<source media="(min-width: 768px)" srcset="hero-square.jpg" />
<!-- Small screens: portrait image -->
<img src="hero-portrait.jpg" alt="Hero image" class="responsive-image" />
</picture>
Responsive Images with srcset
<img
src="image-800w.jpg"
srcset="
image-400w.jpg 400w,
image-800w.jpg 800w,
image-1200w.jpg 1200w,
image-1600w.jpg 1600w
"
sizes="
(max-width: 480px) 100vw,
(max-width: 768px) 80vw,
(max-width: 1200px) 60vw,
40vw
"
alt="Responsive image"
class="responsive-image"
/>
Responsive Typography
Fluid Typography
/* Traditional approach */
.traditional-text {
font-size: 1rem;
}
@media (min-width: 768px) {
.traditional-text {
font-size: 1.125rem;
}
}
@media (min-width: 1024px) {
.traditional-text {
font-size: 1.25rem;
}
}
/* Modern fluid approach */
.fluid-text {
font-size: clamp(1rem, 2.5vw, 1.5rem);
}
.fluid-heading {
font-size: clamp(1.5rem, 5vw, 3rem);
line-height: 1.2;
}
.fluid-spacing {
margin-bottom: clamp(1rem, 3vw, 2rem);
padding: clamp(1rem, 4vw, 3rem);
}
Responsive Line Height
.responsive-typography {
font-size: clamp(1rem, 2.5vw, 1.25rem);
line-height: clamp(1.4, 1.4 + 0.5vw, 1.7);
letter-spacing: clamp(-0.02em, 0vw, 0.02em);
}
Container Queries (Modern)
.card-container {
container-type: inline-size; /* Enable container queries */
}
.card {
padding: 1rem;
}
/* Container query syntax */
@container (min-width: 300px) {
.card {
display: flex;
gap: 1rem;
}
}
@container (min-width: 500px) {
.card {
padding: 2rem;
font-size: 1.125rem;
}
}
Responsive Navigation
Mobile-First Navigation
<nav class="navbar">
<div class="nav-brand">
<a href="/">Brand</a>
</div>
<button class="nav-toggle" aria-label="Toggle navigation">
<span></span>
<span></span>
<span></span>
</button>
<div class="nav-menu">
<a href="#home" class="nav-link">Home</a>
<a href="#about" class="nav-link">About</a>
<a href="#services" class="nav-link">Services</a>
<a href="#contact" class="nav-link">Contact</a>
</div>
</nav>
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
background-color: #fff;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.nav-brand a {
font-size: 1.5rem;
font-weight: bold;
text-decoration: none;
color: #333;
}
/* Mobile hamburger menu */
.nav-toggle {
display: flex;
flex-direction: column;
gap: 4px;
background: none;
border: none;
cursor: pointer;
padding: 0.5rem;
}
.nav-toggle span {
width: 25px;
height: 3px;
background-color: #333;
transition: all 0.3s ease;
}
/* Mobile menu hidden by default */
.nav-menu {
position: fixed;
top: 70px;
left: -100%;
width: 100%;
height: calc(100vh - 70px);
background-color: #fff;
display: flex;
flex-direction: column;
align-items: center;
gap: 2rem;
padding-top: 3rem;
transition: left 0.3s ease;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.nav-menu.active {
left: 0; /* Show menu */
}
.nav-link {
font-size: 1.125rem;
text-decoration: none;
color: #333;
padding: 1rem;
transition: color 0.3s ease;
}
.nav-link:hover {
color: #007bff;
}
/* Desktop navigation */
@media (min-width: 768px) {
.nav-toggle {
display: none; /* Hide hamburger */
}
.nav-menu {
position: static; /* Reset positioning */
height: auto;
background: none;
flex-direction: row;
padding-top: 0;
box-shadow: none;
gap: 2rem;
}
.nav-link {
font-size: 1rem;
padding: 0.5rem;
}
}
Responsive Cards
<div class="card-grid">
<div class="card">
<img src="image1.jpg" alt="Card 1" class="card-image" />
<div class="card-content">
<h3 class="card-title">Card Title 1</h3>
<p class="card-description">Description for card 1</p>
<a href="#" class="card-button">Learn More</a>
</div>
</div>
<!-- More cards... -->
</div>
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
gap: clamp(1rem, 3vw, 2rem);
padding: clamp(1rem, 4vw, 3rem);
}
.card {
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
}
.card-image {
width: 100%;
height: 200px;
object-fit: cover;
}
.card-content {
padding: clamp(1rem, 4vw, 2rem);
}
.card-title {
font-size: clamp(1.125rem, 3vw, 1.5rem);
margin-bottom: 0.75rem;
color: #333;
}
.card-description {
font-size: clamp(0.875rem, 2vw, 1rem);
line-height: 1.6;
color: #666;
margin-bottom: 1.5rem;
}
.card-button {
display: inline-block;
padding: 0.75rem 1.5rem;
background-color: #007bff;
color: white;
text-decoration: none;
border-radius: 6px;
font-size: 0.875rem;
font-weight: 500;
transition: background-color 0.3s ease;
}
.card-button:hover {
background-color: #0056b3;
}
/* Single column on very small screens */
@media (max-width: 480px) {
.card-grid {
grid-template-columns: 1fr;
}
}
Responsive Layout Patterns
Holy Grail Layout
.holy-grail {
display: grid;
min-height: 100vh;
grid-template-rows: auto 1fr auto;
}
.header,
.footer {
background-color: #f8f9fa;
padding: 1rem;
text-align: center;
}
.main-container {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
padding: 1rem;
}
.content {
order: 1;
}
.sidebar-left {
order: 2;
}
.sidebar-right {
order: 3;
}
@media (min-width: 768px) {
.main-container {
grid-template-columns: 200px 1fr 150px;
}
.content {
order: 2;
}
.sidebar-left {
order: 1;
}
.sidebar-right {
order: 3;
}
}
Pancake Stack
.pancake-stack {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.stack-header,
.stack-footer {
flex-shrink: 0; /* Don't shrink */
padding: 2rem;
background-color: #f8f9fa;
}
.stack-main {
flex: 1; /* Take remaining space */
padding: 2rem;
}
Sidebar Layout
.sidebar-layout {
display: grid;
grid-template-columns: 1fr;
min-height: 100vh;
}
.sidebar {
background-color: #2c3e50;
color: white;
padding: 2rem;
order: 2;
}
.main-content {
padding: 2rem;
order: 1;
}
@media (min-width: 768px) {
.sidebar-layout {
grid-template-columns: 250px 1fr;
}
.sidebar {
order: 1;
}
.main-content {
order: 2;
}
}
Responsive Forms
<form class="responsive-form">
<div class="form-grid">
<div class="form-group">
<label for="name">Name</label>
<input type="text" id="name" name="name" required />
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" required />
</div>
<div class="form-group form-full">
<label for="message">Message</label>
<textarea id="message" name="message" rows="4"></textarea>
</div>
<button type="submit" class="submit-button">Send Message</button>
</div>
</form>
.responsive-form {
max-width: 800px;
margin: 0 auto;
padding: clamp(1rem, 4vw, 3rem);
}
.form-grid {
display: grid;
grid-template-columns: 1fr;
gap: 1.5rem;
}
.form-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.form-group label {
font-weight: 500;
color: #333;
}
.form-group input,
.form-group textarea {
padding: 0.75rem;
border: 2px solid #e1e5e9;
border-radius: 6px;
font-size: 1rem;
transition: border-color 0.3s ease;
}
.form-group input:focus,
.form-group textarea:focus {
outline: none;
border-color: #007bff;
}
.submit-button {
padding: 1rem 2rem;
background-color: #007bff;
color: white;
border: none;
border-radius: 6px;
font-size: 1rem;
font-weight: 500;
cursor: pointer;
transition: background-color 0.3s ease;
justify-self: start;
}
.submit-button:hover {
background-color: #0056b3;
}
@media (min-width: 768px) {
.form-grid {
grid-template-columns: 1fr 1fr;
}
.form-full {
grid-column: 1 / -1; /* Span full width */
}
.submit-button {
grid-column: 1 / -1;
justify-self: end;
}
}
Performance Optimization
Critical CSS
/* Critical styles for above-the-fold content */
.critical {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: system-ui, sans-serif;
}
/* Non-critical styles loaded later */
@media print {
.non-critical {
display: none;
}
}
Conditional Loading
<head>
<!-- Critical CSS inline -->
<style>
/* Critical styles here */
</style>
<!-- Non-critical CSS with media queries -->
<link rel="stylesheet" href="desktop.css" media="(min-width: 1024px)" />
<link rel="stylesheet" href="print.css" media="print" />
</head>
Optimize Images
.optimized-image {
max-width: 100%;
height: auto;
loading: lazy; /* Native lazy loading */
decoding: async; /* Async decoding */
}
/* WebP support detection */
.webp .hero-image {
background-image: url("hero.webp");
}
.no-webp .hero-image {
background-image: url("hero.jpg");
}
Testing Responsive Design
Browser DevTools
- Toggle device toolbar (Ctrl+Shift+M)
- Select different devices atau custom size
- Test landscape/portrait orientation
- Check different pixel densities
- Simulate slow networks
Testing Checklist
✅ Navigation works on all screen sizes
✅ Text readable without zooming
✅ Images scale properly
✅ Forms usable on mobile
✅ Buttons large enough for touch
✅ Fast loading on mobile networks
Common Tools
- Chrome DevTools - Built-in responsive testing
- Firefox Responsive Design Mode - Excellent for testing
- BrowserStack - Real device testing
- Responsively App - All devices at once
Common Responsive Mistakes
❌ Fixed Widths
/* Bad */
.container {
width: 1200px; /* Fixed width */
}
/* Good */
.container {
width: 100%;
max-width: 1200px; /* Flexible width */
margin: 0 auto;
}
❌ Small Touch Targets
/* Bad */
.button {
padding: 4px 8px; /* Too small for touch */
}
/* Good */
.button {
padding: 12px 24px; /* Minimum 44px touch target */
min-height: 44px;
}
❌ Horizontal Scrolling
/* Bad */
.wide-content {
width: 1000px; /* Causes horizontal scroll */
}
/* Good */
.wide-content {
width: 100%;
max-width: 1000px;
overflow-x: auto; /* Handle overflow */
}
Modern Responsive Techniques
Intrinsic Web Design
.intrinsic-layout {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
gap: clamp(1rem, 3vw, 2rem);
}
Aspect Ratio
.aspect-ratio-box {
aspect-ratio: 16 / 9; /* Modern aspect ratio */
background-color: #f0f0f0;
}
/* Fallback for older browsers */
.aspect-ratio-fallback {
position: relative;
padding-bottom: 56.25%; /* 16:9 ratio */
height: 0;
}
.aspect-ratio-fallback img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
Container Units
.container-aware {
container-type: inline-size;
padding: 2cqw; /* 2% of container width */
}
@container (min-width: 400px) {
.nested-component {
display: grid;
grid-template-columns: 1fr 1fr;
}
}
Best Practices
1. Mobile-First Always
/* Start with mobile styles */
.component {
flex-direction: column;
}
/* Enhance for larger screens */
@media (min-width: 768px) {
.component {
flex-direction: row;
}
}
2. Use Logical Properties
.modern-spacing {
margin-inline: auto; /* Horizontal margins */
padding-block: 2rem; /* Vertical padding */
border-inline-start: 3px solid blue; /* Left border in LTR */
}
3. Progressive Enhancement
/* Base experience */
.enhanced-feature {
background-color: #f0f0f0;
}
/* Enhanced for capable browsers */
@supports (backdrop-filter: blur(10px)) {
.enhanced-feature {
background-color: rgba(240, 240, 240, 0.8);
backdrop-filter: blur(10px);
}
}
Kesimpulan
Responsive Design adalah fundamental dalam web development modern. Key points:
- Mobile-first approach untuk better performance
- Flexible units (rem, %, vw, clamp) over fixed pixels
- Progressive enhancement untuk all devices
- Test extensively di real devices
- Performance matters - especially on mobile
Dengan responsive design yang baik, website Anda akan memberikan excellent user experience di semua device!
Selanjutnya kita akan mempelajari CSS Animations - cara menambahkan gerakan dan interaktivitas yang menarik!