CSS3 Advanced Topics


CSS3 Advanced Topics Interview with follow-up questions

1. What is flexbox in CSS3 and how is it used?

Flexbox (Flexible Box Layout) is a CSS layout model designed for one-dimensional layouts — arranging items along a single axis, either a row or a column. You activate it by setting display: flex (block-level) or display: inline-flex (inline-level) on a parent element, which then becomes the flex container; its direct children become flex items.

Container properties:

  • flex-direction: sets the main axis — row (default), row-reverse, column, column-reverse
  • flex-wrap: controls whether items wrap to new lines — nowrap (default), wrap, wrap-reverse
  • justify-content: aligns items along the main axis — flex-start, center, space-between, space-around, space-evenly
  • align-items: aligns items along the cross axis — stretch (default), center, flex-start, flex-end, baseline
  • align-content: aligns multiple rows/columns when wrapping is enabled
  • gap (also row-gap, column-gap): sets spacing between items without using margins

Item properties:

  • flex-grow: factor by which an item grows to fill available space (default 0)
  • flex-shrink: factor by which an item shrinks when space is tight (default 1)
  • flex-basis: the item's initial size before growing or shrinking (default auto)
  • flex: shorthand for flex-grow flex-shrink flex-basisflex: 1 is a common pattern meaning the item grows and shrinks equally
  • align-self: overrides the container's align-items for one item
  • order: controls visual order independent of DOM order

Common gotchas interviewers probe:

  • flex: 1 is shorthand for 1 1 0 — the 0 basis means items share space equally, ignoring their natural size. flex: auto means 1 1 auto, which respects natural size first.
  • min-width: 0 is often needed on flex items containing text or nested flex containers, because flex items default to min-width: auto which prevents proper shrinking.
  • align-items vs justify-content axes swap when flex-direction: column is used — interviewers ask this frequently.
  • gap in flexbox has full browser support since 2021; margins between items were the old workaround.
  • Flexbox does not inherently create equal-height columns in a grid sense; for a true two-dimensional layout, CSS Grid is the better tool.
  • order changes visual order but not the DOM order, which affects accessibility (tab/focus order follows the DOM).

Flexbox is ideal for navigation bars, card rows, centering content, and any UI component that needs items to grow, shrink, and align along one axis.

↑ Back to top

Follow-up 1

Can you explain the difference between flex-grow, flex-shrink, and flex-basis?

Sure! Here's the difference between flex-grow, flex-shrink, and flex-basis:

  • flex-grow: This property determines how much the flex items grow relative to each other when there is extra space in the flex container. It accepts a unitless value that represents the proportion of available space each flex item should take up. For example, if one flex item has a flex-grow value of 2 and another has a value of 1, the first item will take up twice as much space as the second item.

  • flex-shrink: This property determines how much the flex items shrink relative to each other when there is not enough space in the flex container. It also accepts a unitless value that represents the proportion of available space each flex item should give up. For example, if one flex item has a flex-shrink value of 2 and another has a value of 1, the first item will shrink twice as much as the second item.

  • flex-basis: This property specifies the initial size of the flex items before any remaining space is distributed. It can be set to a length value (e.g., pixels or percentages) or the 'auto' keyword. If set to 'auto', the flex items will be sized based on their content.

Follow-up 2

How does the 'justify-content' property work in flexbox?

The 'justify-content' property in flexbox is used to align the flex items along the main axis of the flex container. It controls the distribution of space between and around the flex items. Here are the possible values for 'justify-content':

  • flex-start: The flex items are packed at the start of the flex container.
  • flex-end: The flex items are packed at the end of the flex container.
  • center: The flex items are centered within the flex container.
  • space-between: The flex items are evenly distributed in the flex container, with the first item at the start and the last item at the end.
  • space-around: The flex items are evenly distributed in the flex container, with equal space around them.
  • space-evenly: The flex items are evenly distributed in the flex container, with equal space between them.

Follow-up 3

What is the difference between 'align-items' and 'align-content' in flexbox?

Both 'align-items' and 'align-content' are properties in flexbox that are used to align the flex items along the cross axis of the flex container. However, there is a difference between them:

  • align-items: This property is used to align the flex items individually within the flex container. It controls the alignment of the flex items perpendicular to the main axis. The possible values for 'align-items' are:

    • flex-start: The flex items are aligned at the start of the cross axis.
    • flex-end: The flex items are aligned at the end of the cross axis.
    • center: The flex items are centered along the cross axis.
    • baseline: The flex items are aligned such that their baselines align.
    • stretch: The flex items are stretched to fill the container along the cross axis if needed.
  • align-content: This property is used to align the flex lines within the flex container when there is extra space in the cross axis. It controls the alignment of the flex lines perpendicular to the main axis. The possible values for 'align-content' are:

    • flex-start: The flex lines are packed at the start of the cross axis.
    • flex-end: The flex lines are packed at the end of the cross axis.
    • center: The flex lines are centered along the cross axis.
    • space-between: The flex lines are evenly distributed in the cross axis, with the first line at the start and the last line at the end.
    • space-around: The flex lines are evenly distributed in the cross axis, with equal space around them.
    • stretch: The flex lines are stretched to fill the container along the cross axis if needed.

2. What are pseudo-classes in CSS3 and can you give some examples?

Pseudo-classes are CSS selectors that target elements based on their state, position, or relationship within the document tree. They are prefixed with a single colon (:) and do not require changes to the HTML markup.

User interaction states:

  • :hover — element is being pointed at
  • :focus — element has keyboard/programmatic focus; use this for accessibility, not just :hover
  • :focus-visible — focus is visible (i.e., keyboard navigation), but not when clicking; preferred in 2026 for styling focus rings without affecting mouse users
  • :focus-within — any descendant of the element has focus; useful for styling form wrappers
  • :active — element is being activated (e.g., a button being pressed)

Structural / tree-position:

  • :first-child, :last-child — first or last child of their parent
  • :nth-child(n) — flexible selector; accepts integers, keywords (even, odd), or the An+B formula; e.g., :nth-child(3n+1)
  • :nth-of-type(n) — like :nth-child but scoped to elements of the same type
  • :only-child, :only-of-type — matches when there is exactly one child
  • :not(selector) — negation; accepts a full selector list in modern CSS, e.g., :not(.disabled, [aria-hidden])
  • :is(selector-list) — matches if any selector in the list matches; reduces repetition and takes the specificity of its most specific argument
  • :where(selector-list) — same as :is() but always has zero specificity; good for resets and layers
  • :has(selector) — "parent selector"; selects an element if it contains a matching descendant, e.g., form:has(input:invalid) styles the form when it has an invalid input. Fully supported in all major browsers as of 2024.

Form / input states:

  • :checked, :disabled, :enabled, :required, :optional
  • :valid, :invalid, :in-range, :out-of-range
  • :placeholder-shown — input currently showing its placeholder text
  • :user-valid, :user-invalid — like :valid/:invalid but only trigger after the user has interacted with the field, avoiding premature error styling on page load

Other useful pseudo-classes:

  • :root — matches the document root (``); commonly used for CSS custom property declarations
  • :empty — element with no children (including no text nodes)
  • :target — element whose id matches the URL fragment
  • :any-link — matches any element that is a hyperlink, regardless of :visited state

Common interview gotcha: :nth-child counts all sibling elements regardless of type, while :nth-of-type counts only siblings of the same element type. Mixing them up is a classic source of bugs. Also note that :has() is now a game-changer for reducing JavaScript-driven class toggling — interviewers increasingly ask about it.

↑ Back to top

Follow-up 1

How is the ':hover' pseudo-class used?

The ':hover' pseudo-class is used to select an element when the user hovers over it. It is commonly used to change the appearance of links when they are hovered. Here is an example:

a:hover {
    color: red;
    text-decoration: underline;
}

In this example, when the user hovers over a link, the text color will change to red and it will be underlined.

Follow-up 2

What is the difference between ':nth-child' and ':nth-of-type' pseudo-classes?

The ':nth-child' and ':nth-of-type' pseudo-classes are used to select elements based on their position in the parent. The main difference between them is how they count the elements.

  • ':nth-child' counts all the children of the parent, regardless of their type. For example, if you have a list with both 'li' and 'div' elements, ':nth-child(2)' will select the second child element, regardless of its type.

  • ':nth-of-type' counts only the children of the same type as the element you are applying the pseudo-class to. For example, if you have a list with both 'li' and 'div' elements, ':nth-of-type(2)' will select the second 'li' element.

Here is an example:

li:nth-child(2) {
    color: red;
}

li:nth-of-type(2) {
    color: blue;
}

In this example, if you have a list with three 'li' elements, the second 'li' element will be red using ':nth-child(2)' and blue using ':nth-of-type(2)'.

Follow-up 3

Can you explain the ':not' pseudo-class and its usage?

The ':not' pseudo-class is used to select elements that do not match a specific selector. It allows you to exclude certain elements from a selection. Here is an example:

p:not(.special) {
    color: blue;
}

In this example, all 'p' elements that do not have the class 'special' will have a blue color. The ':not' pseudo-class can also be combined with other selectors to create more complex selections. For example:

p:not(.special, .highlight) {
    color: blue;
}

In this example, all 'p' elements that do not have either the class 'special' or 'highlight' will have a blue color.

3. What are media queries in CSS3 and how are they used?

Media queries let you apply CSS rules conditionally based on characteristics of the viewport, device, or output medium. They are the backbone of responsive design.

Basic syntax:

@media screen and (max-width: 768px) {
  /* rules for screens up to 768px wide */
}

Media types: screen, print, all (default). speech is part of the spec but rarely used. tv, handheld, etc., were deprecated long ago.

Common media features:

  • width, min-width, max-width — viewport width (most commonly used)
  • height, min-height, max-height
  • orientation: portrait | landscape
  • resolution — screen pixel density
  • prefers-color-scheme: dark | light — system-level dark mode preference; now standard practice
  • prefers-reduced-motion: reduce — respect users who disable animations; should be in every production codebase
  • prefers-contrast: more | less
  • hover: none — detects touch-only devices (no pointer hover); useful for hiding hover-only UI
  • pointer: coarse | fine — coarse means touch, fine means mouse; lets you size tap targets appropriately

Range syntax (modern CSS): The older min-width/max-width pattern is being replaced by range syntax for clarity:

@media (width >= 768px) and (width < 1200px) {
  /* tablet range */
}

This is supported in all modern browsers and avoids the confusion of min/max off-by-one overlaps.

Container queries (@container): Introduced and now fully supported, container queries are the 2026 answer to component-level responsiveness. Instead of querying the viewport, you query a named container's size:

.card-wrapper {
  container-type: inline-size;
  container-name: card;
}

@container card (width >= 400px) {
  .card { flex-direction: row; }
}

This solves the long-standing problem where components behave differently depending on where they are placed, not just what the viewport size is.

@layer interaction: Media queries can be combined with cascade layers for fine-grained specificity control. Putting responsive overrides in a separate layer prevents specificity wars.

Common gotchas:

  • Mobile-first means using min-width (add styles as screens get bigger), not max-width (strip styles as screens get smaller). Mobile-first results in simpler, additive CSS.
  • Without the `tag, media queries based onwidth` do not behave correctly on mobile browsers, which default to a virtual 980px viewport.
  • max-width: 768px and min-width: 768px both trigger at exactly 768px — be precise about whether your breakpoints should be inclusive or exclusive.
  • prefers-reduced-motion is not optional for accessibility compliance (WCAG 2.2 AA).
↑ Back to top

Follow-up 1

Can you explain how to use media queries for responsive design?

To use media queries for responsive design, you need to define different CSS rules for different screen sizes or devices. Here's an example:

/* Default styles for all screens */

/* CSS rules for screens with a maximum width of 600px */
@media screen and (max-width: 600px) {
  /* CSS rules for screens with a maximum width of 600px */
}

/* CSS rules for screens with a minimum width of 601px */
@media screen and (min-width: 601px) {
  /* CSS rules for screens with a minimum width of 601px */
}

In this example, the default styles will apply to all screens, but the media queries will override those styles for screens with a maximum width of 600 pixels or a minimum width of 601 pixels.

Follow-up 2

What is the difference between 'min-width' and 'max-width' in media queries?

In media queries, 'min-width' and 'max-width' are used to specify the range of screen sizes for which the CSS rules should apply. The main difference between them is the direction of the comparison:

  • 'min-width' applies the CSS rules when the screen width is equal to or greater than the specified value.
  • 'max-width' applies the CSS rules when the screen width is equal to or less than the specified value.

For example:

@media screen and (min-width: 600px) {
  /* CSS rules for screens with a minimum width of 600px */
}

@media screen and (max-width: 600px) {
  /* CSS rules for screens with a maximum width of 600px */
}

In this example, the first media query will apply the CSS rules for screens with a minimum width of 600 pixels, while the second media query will apply the CSS rules for screens with a maximum width of 600 pixels.

Follow-up 3

How can you use media queries to target specific devices or orientations?

Media queries can be used to target specific devices or orientations by combining media types and conditions. Here are some examples:

  • Targeting specific devices:
  @media screen and (max-width: 600px) {
    /* CSS rules for screens with a maximum width of 600px */
  }

In this example, the media query will only apply to screens with a maximum width of 600 pixels, regardless of the device.

  • Targeting specific orientations:
  @media screen and (orientation: landscape) {
    /* CSS rules for screens in landscape orientation */
  }

In this example, the media query will only apply to screens in landscape orientation.

  • Targeting specific devices and orientations:
  @media screen and (max-width: 600px) and (orientation: portrait) {
    /* CSS rules for screens with a maximum width of 600px and portrait orientation */
  }

In this example, the media query will only apply to screens with a maximum width of 600 pixels and portrait orientation.

4. What is the grid layout in CSS3 and how does it work?

CSS Grid is a two-dimensional layout system that lets you place elements into explicit rows and columns, giving you precise control over both axes simultaneously.

Defining a grid:

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto;
  gap: 1rem;
}

Key concepts:

  • grid-template-columns / grid-template-rows — define the track sizes. Units can be px, %, fr (fraction of available space), auto, min-content, max-content, or minmax().
  • fr unit — distributes remaining space proportionally after fixed sizes are resolved. 1fr 2fr creates a 1:2 split.
  • repeat() — shorthand for repeating tracks; repeat(3, 1fr) creates three equal columns.
  • minmax(min, max) — a track grows between a minimum and maximum size.
  • auto-fill vs auto-fit: both create as many tracks as fit, but auto-fit collapses empty tracks while auto-fill preserves them.
  • gap (formerly grid-gap) — sets spacing between rows and columns.

Placing items: Items auto-place by default following the grid auto-placement algorithm. You can override this:

.item {
  grid-column: 1 / 3;   /* span from line 1 to line 3 */
  grid-row: 2 / 4;
}

Shorthand: grid-area: row-start / col-start / row-end / col-end.

Named areas:

.container {
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
}
.header { grid-area: header; }

This is highly readable and makes layout changes trivial.

Alignment:

  • justify-items / align-items — aligns all items within their cells (inline vs block axis)
  • justify-content / align-content — aligns the grid tracks within the container when there is extra space
  • justify-self / align-self — per-item overrides

Subgrid: grid-template-columns: subgrid lets a nested grid inherit its parent's track definitions. This solves the long-standing problem of aligning content inside cards to a parent grid. Subgrid is now fully supported across all major browsers.

Common gotchas:

  • Grid lines are numbered starting at 1 (not 0). Negative numbers count from the end (-1 is the last line).
  • grid-column: span 2 is relative spanning; grid-column: 1 / 3 is explicit placement — they look similar but behave differently with auto-placement.
  • Grid does not replace Flexbox — Grid excels at two-dimensional page/component layout; Flexbox is better for one-dimensional item distribution within a component.
  • display: grid does not affect elements outside the grid container; children become grid items, but grandchildren do not.
↑ Back to top

Follow-up 1

Can you explain the difference between 'grid-template-rows' and 'grid-template-columns'?

'grid-template-rows' and 'grid-template-columns' are properties used to define the rows and columns of a grid container in CSS grid layout.

'grid-template-rows' is used to specify the height of each row in the grid. You can define the height using absolute values (pixels, percentages) or relative values (fr units).

'grid-template-columns' is used to specify the width of each column in the grid. It follows the same syntax as 'grid-template-rows' but applies to columns instead of rows.

For example, to create a grid with two rows and three columns, you can use the following CSS:

.grid-container {
  display: grid;
  grid-template-rows: 1fr 1fr;
  grid-template-columns: 1fr 1fr 1fr;
}

Follow-up 2

How does 'grid-gap' work in CSS grid layout?

'grid-gap' is a property in CSS grid layout that allows you to specify the size of the gap between grid items. It defines the space between rows and columns in the grid.

You can set the value of 'grid-gap' using one or two values. If you specify one value, it will be applied to both the row and column gaps. If you specify two values, the first value will be applied to the row gap and the second value to the column gap.

For example, to create a grid with a 20px gap between rows and a 10px gap between columns, you can use the following CSS:

.grid-container {
  display: grid;
  grid-gap: 20px 10px;
}

Follow-up 3

What is the purpose of 'grid-auto-flow' property in CSS grid layout?

'grid-auto-flow' is a property in CSS grid layout that controls how grid items are placed in the grid when there are more items than available cells.

By default, 'grid-auto-flow' is set to 'row', which means that grid items are placed in rows from left to right and top to bottom. However, you can change this behavior by setting 'grid-auto-flow' to 'column', which will place items in columns from top to bottom and left to right.

Additionally, you can set 'grid-auto-flow' to 'dense', which allows grid items to be placed in empty cells even if it means creating gaps in the grid.

For example, to create a grid where items are placed in columns from top to bottom, you can use the following CSS:

.grid-container {
  display: grid;
  grid-auto-flow: column;
}

5. What are CSS3 transitions and how are they used?

CSS transitions allow you to animate a CSS property from one value to another smoothly over a specified duration, triggered by a state change (like :hover, :focus, or a class being added via JavaScript).

The transition shorthand:

.button {
  background-color: blue;
  transition: background-color 0.3s ease-in-out, transform 0.2s ease;
}
.button:hover {
  background-color: darkblue;
  transform: scale(1.05);
}

The four sub-properties:

  • transition-property — which CSS property to animate (all works but is bad for performance)
  • transition-duration — how long the transition takes (e.g., 300ms, 0.3s)
  • transition-timing-function — easing curve: ease (default), linear, ease-in, ease-out, ease-in-out, or a custom cubic-bezier()
  • transition-delay — how long to wait before starting (useful for staggered effects)

Properties that can be transitioned: Only properties with numeric or color interpolatable values can be transitioned — opacity, transform, color, background-color, width, height, border-radius, etc. Properties like display and visibility cannot be transitioned directly (though display is gaining transition support in 2024+ with the @starting-style rule).

Performance considerations: Animating transform and opacity is GPU-composited and does not trigger layout or paint — these are the only two properties you should animate for high-performance transitions. Animating width, height, top, left, or margin triggers layout recalculation and can cause jank, especially on mobile.

@starting-style (modern CSS): Allows transitioning an element's initial state when it first appears in the DOM or transitions from display: none:

.dialog {
  transition: opacity 0.3s;
  opacity: 1;
}
@starting-style {
  .dialog { opacity: 0; }
}

This is now supported in Chrome, Edge, and Firefox, removing the need for a JavaScript setTimeout hack to trigger enter animations.

Transitions vs animations:

  • Transitions are event-driven (require a state change to trigger) and go from A to B once.
  • CSS animations (@keyframes) run automatically, can loop, and can define multiple intermediate states.

Common gotchas:

  • transition: all catches unintended property changes and can cause performance issues — always name specific properties.
  • A transition on the base element triggers on both entering and leaving a state. To have different durations in each direction, declare separate transitions on the base and the :hover/active state.
  • Transitioning height: auto does not work because auto is not a calculable intermediate value; use max-height as a workaround, or the newer CSS interpolate-size / calc-size() approach now landing in browsers.
↑ Back to top

Follow-up 1

How does the 'transition-delay' property work?

The 'transition-delay' property allows you to specify a delay before the transition starts. This can be useful if you want to stagger the timing of multiple transitions or create a delay before an animation begins.

The value of 'transition-delay' is specified in seconds or milliseconds. Here's an example:

.element {
  transition: width 1s;
  transition-delay: 0.5s;
}

In this example, the transition will start 0.5 seconds after the property change occurs.

Follow-up 2

What properties can be transitioned using CSS3 transitions?

CSS3 transitions can be applied to most CSS properties that accept numeric values. Some common properties that can be transitioned include:

  • width
  • height
  • opacity
  • background-color
  • font-size
  • transform

You can also transition shorthand properties, such as 'margin' or 'padding', which will transition all individual properties that make up the shorthand.

Follow-up 3

Can you explain how to use 'transition-timing-function'?

The 'transition-timing-function' property allows you to specify the speed curve of the transition. It determines how intermediate property values are calculated during the transition.

There are several predefined timing functions available, such as 'ease', 'linear', 'ease-in', 'ease-out', and 'ease-in-out'. You can also use the 'cubic-bezier' function to create custom timing functions.

Here's an example that uses the 'ease-in-out' timing function:

.element {
  transition: width 1s;
  transition-timing-function: ease-in-out;
}

This will make the transition start slowly, accelerate in the middle, and then slow down again at the end.

Live mock interview

Mock interview: CSS3 Advanced Topics

Intermediate ~5 min Your own free AI key

Your voice and your AI key never touch our servers; the key stays in this browser and is sent only to Google. Only your round scores are saved to track progress.