Common HTML & CSS technical interview questions spanning beginner to advanced, covering semantics, the box model, layout systems, specificity, accessibility, performance, and modern CSS features.
Elements are the building blocks of HTML, defined by opening and closing tags (e.g., <p>). Attributes provide additional information about elements and are placed inside the opening tag (e.g., class, id, href). Every attribute has a name and usually a value.
Semantic HTML uses meaningful tags (e.g., <article>, <nav>, <header>, <main>) that describe the purpose of the content rather than just its presentation. It improves accessibility for screen readers, helps search engines understand page structure, and makes code easier to maintain.
Every HTML element is represented as a rectangular box consisting of content, padding, border, and margin (from inside out). Understanding the box model is essential for controlling layout and spacing. By default, width and height apply only to the content area; adding box-sizing: border-box includes padding and border in the declared dimensions.
Block elements (e.g., <div>, <p>) start on a new line and take up the full available width. Inline elements (e.g., <span>, <a>) flow within text and do not start a new line; you cannot set width/height on them. Inline-block elements flow like inline elements but respect width, height, and vertical margin/padding.
Specificity determines which CSS rule wins when multiple rules target the same element. It is calculated as a four-part value: inline styles (1,0,0,0), IDs (0,1,0,0), classes/attributes/pseudo-classes (0,0,1,0), and elements/pseudo-elements (0,0,0,1). The rule with the highest specificity value is applied; !important overrides all specificity.
An id selector (#myId) targets a single unique element on a page and has higher specificity than a class. A class selector (.myClass) can be applied to multiple elements and reused throughout the page. Best practice is to use classes for styling and reserve ids for JavaScript hooks or anchor links.
Some CSS properties (e.g., color, font-size, line-height) are automatically inherited by child elements from their parent. Others (e.g., margin, padding, border) are not inherited by default. You can explicitly control inheritance with the inherit, initial, and unset keyword values.
Relative positions the element relative to its normal document flow position without removing it from flow. Absolute removes the element from flow and positions it relative to the nearest positioned ancestor. Fixed positions the element relative to the viewport so it stays put during scrolling. Sticky is a hybrid — it scrolls normally until a threshold is met, then behaves like fixed.
Flexbox is a one-dimensional layout system best suited for distributing items along a single axis (row or column), such as navigation bars or card rows. CSS Grid is two-dimensional and excels at defining explicit rows and columns simultaneously, making it ideal for full page layouts or complex component grids. In practice, they are often combined: Grid for the macro layout, Flexbox for component-level alignment.
px is an absolute unit. em is relative to the font-size of the element itself (or its parent for font-size), which can compound in nested elements. rem (root em) is always relative to the root (<html>) font-size, making it more predictable for scalable design. % is relative to the parent element's corresponding property (usually width or font-size).
Pseudo-classes target elements in a specific state using a single colon (e.g., :hover, :focus, :nth-child()). Pseudo-elements create virtual sub-elements or target specific parts of content using a double colon (e.g., ::before, ::after, ::first-line). Pseudo-classes affect existing elements; pseudo-elements generate new render-only content.
display: none removes the element completely from the document flow, so it takes up no space. visibility: hidden hides the element visually but preserves the space it occupies in the layout. opacity: 0 also hides content visually while keeping its space, but unlike visibility: hidden, events like click can still fire on it.
Media queries apply CSS rules only when specific conditions (such as viewport width) are met, using the @media rule. In a mobile-first approach you write base styles for small screens first, then use min-width breakpoints to progressively add or override styles for larger screens (e.g., @media (min-width: 768px) {}). This is preferred over desktop-first because it results in simpler, more performant styles for mobile devices.
Both async and defer allow the browser to continue parsing HTML while the script downloads. With async, the script executes immediately after downloading, potentially before HTML parsing completes, which can cause issues with DOM-dependent scripts. With defer, execution is delayed until the DOM is fully parsed, and multiple deferred scripts execute in order — making defer the safer default for most scripts.
A stacking context is an independent layer in which child elements are painted relative to each other. z-index only works on positioned elements (position other than static) or elements with certain CSS properties (opacity, transform, etc.) that create a new stacking context. Elements in a higher stacking context always appear above those in a lower one, regardless of z-index values within nested contexts.
CSS custom properties (declared as --property-name: value on a selector and consumed via var(--property-name)) are native to the browser, live in the cascade, and can be changed dynamically at runtime via JavaScript or media queries. Preprocessor variables (Sass/Less) are compiled away and cannot change at runtime. Custom properties also inherit and can be scoped to a selector, enabling powerful theming patterns.
Both are used with repeat() to create responsive grids without media queries (e.g., repeat(auto-fill, minmax(200px, 1fr))). auto-fill creates as many tracks as can fit, leaving empty tracks if there are fewer items. auto-fit collapses empty tracks, causing existing items to expand and fill the available space. The difference is only visible when items do not fill all available columns.
Avoid deeply nested selectors as they increase selector matching cost. Prefer classes over expensive selectors like :nth-child() on large lists. Minimize layout-triggering properties (width, height, top) in animations — favor transform and opacity which can be GPU-composited. Use will-change sparingly to promote elements to their own compositor layer, and consider Critical CSS to inline above-the-fold styles for faster first paint.
The contain property tells the browser that an element's subtree is independent of the rest of the page, limiting the scope of layout, paint, and style recalculations. For example, contain: layout means changes inside the element cannot affect outside layout. This is a key performance optimization for component-heavy UIs, as it prevents expensive full-page reflows when isolated components change.
Use semantic HTML elements so assistive technologies understand structure without extra ARIA. Add ARIA roles/labels only when native semantics are insufficient. Ensure sufficient color contrast ratios (WCAG AA requires 4.5:1 for normal text). Never suppress focus outlines without providing a visible alternative; use :focus-visible for styled focus indicators. Test with keyboard-only navigation and screen readers (e.g., NVDA, VoiceOver).
© RM Full Stack & AI Engineer · All interview questions · Roadmaps · Open the app