Intermediate11 min read

CSS Display and Visibility: Controlling Element Rendering

11 min read
587 words
20 sections15 code blocks

The Display Property

The display property is one of the most important CSS properties. It determines how an element behaves in the document flow — whether it starts a new line, how it sizes itself, and how it interacts with surrounding elements.

Block-Level Elements

display: block elements take up the full width available and start on a new line:

CSS
.block-element {
  display: block;
}

Block element characteristics:

  • Starts on a new line
  • Takes up 100% of parent width by default
  • Width and height can be set
  • Margins work in all directions (top, right, bottom, left)
  • Padding works in all directions

Default block elements include: div, p, h1-h6, section, article, header, footer, form, ul, ol, li.

Inline Elements

display: inline elements flow within text and only take up as much width as their content needs:

CSS
.inline-element {
  display: inline;
}

Inline element characteristics:

  • Does NOT start on a new line
  • Only takes up as much width as needed
  • Width and height are IGNORED
  • Horizontal margins (left/right) work, but vertical margins (top/bottom) do NOT
  • Padding works visually but doesn't push surrounding block elements away vertically

Default inline elements include: span, a, strong, em, img, code, br.

CSS
/* This will NOT work on inline elements */
span {
  width: 200px;   /* IGNORED */
  height: 100px;  /* IGNORED */
  margin-top: 20px; /* IGNORED */
}

/* This WILL work */
span {
  margin-left: 10px;   /* Works */
  margin-right: 10px;  /* Works */
  padding: 5px 10px;   /* Works visually */
}

Inline-Block Elements

display: inline-block combines the best of both worlds — elements flow inline like text, but you can set width, height, and vertical margins:

CSS
.inline-block-element {
  display: inline-block;
}

Inline-block characteristics:

  • Does NOT start on a new line (flows inline)
  • Width and height CAN be set
  • Margins work in ALL directions
  • Padding works in ALL directions and affects surrounding elements

Common Use Cases

CSS
/* Navigation items side by side */
.nav-item {
  display: inline-block;
  padding: 10px 20px;
  margin: 0 5px;
}

/* Tags or badges */
.tag {
  display: inline-block;
  padding: 4px 12px;
  background: #e0e0e0;
  border-radius: 12px;
  font-size: 0.875rem;
}

Display: None

display: none completely removes an element from the page — it takes up no space and is invisible:

CSS
.hidden {
  display: none;
}

The element is:

  • Not visible on the page
  • Not in the document flow (no space reserved)
  • Not accessible to screen readers
  • Still present in the HTML source

Visibility: Hidden

visibility: hidden makes an element invisible but it still takes up space:

CSS
.invisible {
  visibility: hidden;
}

The element is:

  • Not visible on the page
  • Still in the document flow (space is reserved)
  • Not accessible to most screen readers
  • The space it occupies appears as blank area

display: none vs visibility: hidden

CSS
/* Element is completely gone from layout */
.gone {
  display: none;
}

/* Element is invisible but space is preserved */
.ghost {
  visibility: hidden;
}

When to use each:

  • display: none: Toggling elements on/off (menus, modals, tabs)
  • visibility: hidden: Hiding elements while preserving layout (avoiding content shifts)

The opacity Property

opacity: 0 is another way to hide elements, but the element remains interactive:

CSS
.transparent {
  opacity: 0;
}
  • Not visible but can still be clicked
  • Still in the document flow
  • Still accessible to screen readers
  • Can be animated with transitions (unlike display: none)
CSS
/* Fade in/out with transitions */
.fade {
  opacity: 0;
  transition: opacity 0.3s ease;
}

.fade.visible {
  opacity: 1;
}

Display: Contents

display: contents makes an element's box disappear while keeping its children in the document flow:

CSS
.wrapper {
  display: contents;
}

The wrapper element effectively becomes invisible to the layout, and its children participate in the parent's layout context. Useful when you need a semantic wrapper that doesn't affect CSS Grid or Flexbox layout.

Display: Flow-Root

display: flow-root creates a new block formatting context, which is useful for containing floats:

CSS
.clearfix {
  display: flow-root;
}

This is the modern replacement for the old clearfix hack.

Practical Patterns

Toggle Element Visibility

CSS
.dropdown-menu {
  display: none;
}

.dropdown:hover .dropdown-menu {
  display: block;
}

Accessible Hiding (Screen Reader Only)

CSS
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

This hides content visually but keeps it accessible to screen readers.

Responsive Show/Hide

CSS
.mobile-menu {
  display: block;
}

.desktop-menu {
  display: none;
}

@media (min-width: 768px) {
  .mobile-menu { display: none; }
  .desktop-menu { display: flex; }
}

Summary

The display property controls how elements behave in the layout: block for full-width elements, inline for text-flow elements, and inline-block for inline elements with full box model control. Use display: none to completely remove elements from the flow, visibility: hidden to hide while preserving space, and opacity: 0 for hideable elements that need smooth transitions. Understanding these properties is essential for building any CSS layout.