Search code examples
cssresponsive-designmedia-queries

Responsive design: How can I hide icon labels for small viewports using only CSS?


I'm working on a responsive layout using the ZURB Foundation framework.

I've added some icons (icon font spans) next to the text on a navigation bar, and here's what I would like to happen:

When the viewport is not wide enough to display all the navigation items on one line, the text labels for only the items that would cascade to the next line should be hidden and the font-size (icon size) for that item should be increased to a new fixed value.

I'm attaching 3 images (I just cheated with chrome inspector) to demonstrate what I'm looking for.

Is this possible without JavaScript? If so, how?

Fullscreen

Windowed

Mobile


Solution

  • I have found a solution by iterating on the answer by Charles-Edouard Coste. I am using Sass but I will first show its CSS output:

    nav .nav-bar .icon {
      font-size: 24px;
      padding-right: 4px;
    }
    
    @media only screen and (max-width: 700px) {
      nav .nav-bar li:nth-child(1) .icon-label {
        display: none;
      }
    }
    @media only screen and (max-width: 800px) {
      nav .nav-bar li:nth-child(2) .icon-label {
        display: none;
      }
    }
    @media only screen and (max-width: 900px) {
      nav .nav-bar li:nth-child(3) .icon-label {
        display: none;
      }
    }
    @media only screen and (max-width: 1000px) {
      nav .nav-bar li:nth-child(4) .icon-label {
        display: none;
      }
    }
    @media only screen and (max-width: 1100px) {
      nav .nav-bar li:nth-child(5) .icon-label {
        display: none;
      }
    }
    

    This solution works hiding one label at each hundred pixel decrement. Unfortunately, it requires a new rule for each element in the list, and therefore it requires that the stylesheet either

    1. have exact knowledge of the list length, or
    2. include potentially unused directives up to a reasonable maximum length.

    I have opted to create a Sass mixin for reuse and to make the source less verbose.

    @mixin iconlist( $min-width, $label-selector, $step: 100px, $count: 5 )
      //
       The iconlist() mixin will responsively hide labels, 
       starting from the last, as the viewport width is decreased.
    
       This can be included in a horizontal list to show only icons
       on small screens, while still displaying as many labels as
       possible, assuming items are prioritized from most important
       to least.
    
      @for $i from 1 through $count
        $max-width: $min-width + ( $step * $i )
        @media only screen and (max-width: #{$max-width})
          li:nth-child(#{$i})
            #{$label-selector}
              display: none
    

    Usage

    .nav-bar
      // Responsively hide 0-3 labels from the end of the list.
      @include iconlist(600px, '.icon-label', 100px, 3)
    

    If anyone cares to suggest a refactor that results in smaller or better-decoupled CSS, that would be awesome! But I'm not sure how it would be done.