Practice CSS
You’ve read the lessons — now prove it. Take the quiz for instant feedback, then work the coding exercises. Try each one yourself before you reveal the solution.
Quick quiz
18 questions- 1
Which CSS selector has the highest specificity?
- 2
What does
box-sizing: border-boxdo? - 3
Given
margin: 10px 20px 30px, what is the left margin? - 4
Which value of
positionremoves an element from normal document flow and positions it relative to the nearest positioned ancestor? - 5
What CSS property controls the stacking order of positioned elements?
- 6
In a flex container with
justify-content: space-between, where are the first and last items placed? - 7
What does
flex: 1expand to? - 8
Which CSS Grid property defines the number and size of columns?
- 9
What unit is
1remrelative to? - 10
Which pseudo-class targets an element only when it receives keyboard focus?
- 11
What does the CSS rule
transition: opacity 0.3s easedo? - 12
Which media query activates styles for screens narrower than 768px?
- 13
What does
animation-fill-mode: bothdo? - 14
Which CSS function clamps a value between a minimum and maximum?
- 15
What does
filter: drop-shadow(...)do differently frombox-shadow? - 16
What CSS property must you set on a parent element to make it a container query context?
- 17
Inside
calc(), which of the following is valid CSS? - 18
What is the purpose of
@propertyin CSS?
Coding exercises
8 tasksFluid Typography with clamp()
MediumWrite CSS so that .hero-title has a font size that is never smaller than `1.5rem` and never larger than `3.5rem`, scaling smoothly based on the viewport width. Use clamp() with a viewport-relative preferred value of 3vw + 1rem. Also set line-height: 1.15 and letter-spacing: -0.02em.
💡 Show hint
The syntax is clamp(min, preferred, max). Combine a vw unit with a rem inside the preferred value using calc() or the + operator directly inside clamp().
✅ Show solution
.hero-title {
font-size: clamp(1.5rem, 3vw + 1rem, 3.5rem);
line-height: 1.15;
letter-spacing: -0.02em;
}Glassmorphism Card
MediumStyle a .glass-card element to look like frosted glass. It should have: a semi-transparent white background (rgba(255,255,255,0.15)), a light white border (1px solid rgba(255,255,255,0.25)), 16px border radius, 2rem padding, and a backdrop blur of 20px that blurs whatever is behind it. Include the -webkit- prefixed fallback.
💡 Show hint
Use backdrop-filter: blur(20px) and also add -webkit-backdrop-filter: blur(20px) for Safari support.
✅ Show solution
.glass-card {
background: rgba(255, 255, 255, 0.15);
border: 1px solid rgba(255, 255, 255, 0.25);
border-radius: 16px;
padding: 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
}Container Query Card
HardSet up a .card-wrapper as a named container called "card" with inline-size containment. Inside it, write a @container rule so that when the wrapper is at least 420px wide, the .card switches from a single-column grid to a two-column grid with columns "100px 1fr" and a 1rem gap. By default .card should be display: grid; grid-template-columns: 1fr; gap: 1rem;.
💡 Show hint
Use container: card / inline-size on the wrapper, then write @container card (min-width: 420px) { .card { ... } }.
✅ Show solution
.card-wrapper {
container: card / inline-size;
}
.card {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
}
@container card (min-width: 420px) {
.card {
grid-template-columns: 100px 1fr;
gap: 1rem;
}
}Style a Navigation Bar
EasyGiven an <ul> with class nav, write CSS to display the list items horizontally in a row with no bullets, a dark background (#1a1a2e), and white links. Each list item should have 16px horizontal padding.
/* Style the nav */
.nav {
}
.nav li {
}
.nav a {
}💡 Show hint
Use display: flex on .nav and list-style: none to remove bullets. Set text-decoration: none on links.
✅ Show solution
.nav {
display: flex;
list-style: none;
margin: 0;
padding: 0;
background-color: #1a1a2e;
}
.nav li {
padding: 0 16px;
}
.nav a {
color: #ffffff;
text-decoration: none;
display: block;
padding: 12px 0;
}Centered Card with Box Model
EasyWrite CSS for a .card element that is 400px wide, has 24px padding, a 1px solid #e2e8f0 border, 8px border radius, and is horizontally centered on the page. Ensure padding does not add to the total width.
💡 Show hint
Use box-sizing: border-box to keep the total width at 400px. Use margin: 0 auto to center a block element.
✅ Show solution
.card {
box-sizing: border-box;
width: 400px;
padding: 24px;
border: 1px solid #e2e8f0;
border-radius: 8px;
margin: 0 auto;
}Flexbox Holy Grail Layout
MediumCreate a classic holy grail layout with three columns using Flexbox. The .layout container holds .sidebar-left (200px wide), .main (takes all remaining space), and .sidebar-right (200px wide). All columns should stretch to the same height. Add 16px gap between columns.
.layout {
}
.sidebar-left,
.sidebar-right {
}
.main {
}💡 Show hint
Set display: flex on .layout. Use flex: 1 on .main so it grows to fill available space. Use a fixed width or flex: 0 0 200px on the sidebars.
✅ Show solution
.layout {
display: flex;
align-items: stretch;
gap: 16px;
}
.sidebar-left,
.sidebar-right {
flex: 0 0 200px;
width: 200px;
}
.main {
flex: 1;
min-width: 0;
}Responsive Image Grid
MediumWrite CSS for a .gallery container that displays .gallery-item elements in a responsive grid. On screens wider than 768px, show 3 equal columns with 16px gap. On smaller screens, show 1 column. Each item should have a fixed height of 200px and the image inside (.gallery-item img) should cover the entire item without distortion.
💡 Show hint
Use grid-template-columns: repeat(3, 1fr) for the 3-column layout and a @media query for the 1-column fallback. Use object-fit: cover on the img.
✅ Show solution
.gallery {
display: grid;
grid-template-columns: 1fr;
gap: 16px;
}
.gallery-item {
height: 200px;
overflow: hidden;
}
.gallery-item img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
@media (min-width: 768px) {
.gallery {
grid-template-columns: repeat(3, 1fr);
}
}Animated Tooltip with Pseudo-elements
HardCreate a CSS-only tooltip for a .tooltip-trigger element. The tooltip text is stored in a data-tip attribute. When the user hovers over .tooltip-trigger, a tooltip box should appear above the element using ::before (the bubble) and ::after (a small arrow pointing down). The tooltip should fade in using a CSS transition (opacity from 0 to 1 over 0.2s). Use position: absolute for the tooltip and ensure .tooltip-trigger is the positioning context. Do not use JavaScript.
/* The trigger element already has position: relative */
.tooltip-trigger {
position: relative;
cursor: pointer;
display: inline-block;
}
/* Tooltip bubble */
.tooltip-trigger::before {
}
/* Arrow */
.tooltip-trigger::after {
}
/* Show on hover */
.tooltip-trigger:hover::before,
.tooltip-trigger:hover::after {
}💡 Show hint
Use content: attr(data-tip) on ::before to pull text from the attribute. Position both pseudo-elements with position: absolute; bottom: 100%. Start with opacity: 0 and pointer-events: none, then set opacity: 1 on hover. Use border tricks on ::after to create the arrow triangle.
✅ Show solution
.tooltip-trigger {
position: relative;
cursor: pointer;
display: inline-block;
}
.tooltip-trigger::before {
content: attr(data-tip);
position: absolute;
bottom: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
background-color: #1a1a2e;
color: #ffffff;
padding: 6px 10px;
border-radius: 4px;
white-space: nowrap;
font-size: 0.875rem;
opacity: 0;
pointer-events: none;
transition: opacity 0.2s ease;
z-index: 10;
}
.tooltip-trigger::after {
content: "";
position: absolute;
bottom: calc(100% + 2px);
left: 50%;
transform: translateX(-50%);
border: 6px solid transparent;
border-top-color: #1a1a2e;
opacity: 0;
pointer-events: none;
transition: opacity 0.2s ease;
z-index: 10;
}
.tooltip-trigger:hover::before,
.tooltip-trigger:hover::after {
opacity: 1;
}