CSS Display and Visibility: Controlling Element Rendering
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:
.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:
.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.
/* 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:
.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
/* 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:
.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:
.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
/* 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:
.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)
/* 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:
.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:
.clearfix {
display: flow-root;
}This is the modern replacement for the old clearfix hack.
Practical Patterns
Toggle Element Visibility
.dropdown-menu {
display: none;
}
.dropdown:hover .dropdown-menu {
display: block;
}Accessible Hiding (Screen Reader Only)
.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
.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.