Purpose: Defines how to use breadcrumb navigation in Kuali application interfaces.

Category: Navigation, Breadcrumb

Related jiras:

Process Phase:

  • UXI JIRA Created (insert link above)
  • Component Specification draft complete
  • UXI code review complete
  • Reconcile with UIM and KRAD existing designs
  • Conduct user testing (if needed)
  • Routed for review with Kuali UX Working Group and UX/KRAD Working Group
  • Reviewed with KAI
  • Rice JIRA Created (in KULRICE Project)
  • KRAD Implementation complete
  • Component released (insert rice release version below)

Version: 1.0

 


Description

Breadcrumbs take their name from the Hansel and Gretel fairy tale. The brother and sister would drop bread crumbs along the forest path so they could re-trace their steps and find their way home. As such, a breadcrumb for the Web is similar in that it presents a navigational trail where users have been so they can easily get back to where they came from. They also help alleviate cognitive load of remembering previous steps.

Kuali applications have three different variations of breadcrumbs.

Variations

Desktop Usage

Breadcrumb use in the application view

The breadcrumb navigation directly follows the header and precedes the Document Header. The first link in the breadcrumb navigation is always the root or start of a process. For example, if the root page is "Home", then the first link will always be "Home". The last item in the breadcrumb navigation will be the current page or view and it should not be a link. All of the items between the first and the last should be hierarchical. The breadcrumb should be marked up with an Ordered List.

Location-based breadcrumbs (default)

Path-based breadcrumbs

These are used primarily in modals.

Quick summary of features:

  • Provides a navigational trail reducing the cognitive load to remember where he or she came from
  • Allows quick access to previously accessed links in a given navigational tree
  • Unobtrusive design integrates seamlessly into the interface
  • Provides a secondary drop-down menu allowing users to jump directly to another parent (location-based breadcrumbs only)
  • Uses ARIA properties to assist with screenreaders

When to use this component:

  • When enabled this component should automatically render based on navigation
  • This component should be enabled when navigation will have multiple levels (parents, children, grandchildren, etc.)
  • The Alt variant is mainly used in Proposal Development and Budget in the document header bar

Mobile Usage

Breadcrumbs are responsive

We use a little JavaScript to check window widths and do some magic on the list items within the breadcrumb. When a screen size or browser window is less than 768 pixels across, all but the first and last breadcrumb (usually a link to the Homepage, and the text for the current page) are replaced with a button (...). Activating the button will show all of the breadcrumb options. Closing the options will return the breadcrumb to its clean, collapsed state.

Quick summary of features:

  • Maintains the breadcrumb trail, but saves valuable interface real estate.
  • Provides a link home and the current page for reference
  • Uses an accessible button for the ellipsis
  • Breadcrumb is accessible

When to use this component:

  • This component should be used anytime there's a breadcrumb on the screen. The responsive qualities should be included with this component.
  • There is never a need or a reason to disable the responsive qualities of breadcrumbs. Text will only likely wrap making it look bad.

Demos

Please see my JS Fiddle for working examples.

HTML for path-based breadcrumbs

<div class="uif-breadcrumb" id="path-based" role="navigation">
    <ol class="breadcrumb" role="menubar">
        <li role="presentation"><a role="menuitem" href="#">Home</a></li>
        <li role="presentation"><a role="menuitem" href="#">Parent page</a></li>
        <li role="presentation"><a role="menuitem" href="#">Child page</a></li>
        <li role="presentation"><a role="menuitem" href="#">Grandchild page</a></li>
        <li role="presentation">Great grandchild page</li>
    </ol>
</div>

HTML for location-based breadcrumbs

<div class="uif-breadcrumb" id="location-based" role="navigation">
    <ol class="breadcrumb" role="menubar">
        <li role="presentation"><a role="menuitem" href="#">Home</a></li>
        <li role="presentation"><a role="menuitem" href="#" id="parents_01">Parent page</a>
            <button type="button" class="uif-sub-expand btn btn-link btn-xs" aria-haspopup="true" aria-label="Expand submenu"><span class="icon icon-angle-down"></span></button>
            <ol class="uif-sub-breadcrumb" role="menu" aria-expanded="false" aria-hidden="true" aria-labeledby="parents_01">
                <li role="presentation"><a role="menuitem" href="#">Another parent page</a></li>
                <li role="presentation"><a role="menuitem" href="#">Another parent page</a></li>
                <li role="presentation"><a role="menuitem" href="#">Another parent page</a></li>
                <li role="presentation"><a role="menuitem" href="#">Another parent page</a></li>
                <li role="presentation"><a role="menuitem" href="#">Another parent page</a></li>
            </ol>
        </li>
        <li role="presentation"><a role="menuitem" href="#">Child page</a></li>
        <li role="presentation"><a role="menuitem" href="#">Grandchild page</a></li>
        <li role="presentation">Great grandchild page</li>
    </ol>
</div>

 

CSS for breadcrumbs

The styles are primarily driven by Bootstrap. We do add some however, for the collapsing qualities.

.breadcrumb.open>li + li:before {
    display: none;
}
.uif-breadcrumb ol.open li {
    display: block;
    width: 100%;
    text-align: center;
    padding: 6px;
}
.uif-breadcrumb ol.open li a {
    display: block;
}
.uif-breadcrumb-more {
    display: inline;
}
.uif-breadcrumb-more:before {
    padding: 0 5px;
    color: #ccc;
    content: "/\00a0";
}
.uif-breadcrumb-more button {
    display: inline-block;
}
.uif-breadcrumb-close {
    border-top: 1px solid #ccc;
    margin-top: 12px;
}
.uif-sub-expand {
    display: inline-block;
    height: 18px;
    width: 18px;
    border-radius: 50%;
    padding: 0;
}
.uif-sub-expand:hover, .uif-sub-expand:focus {
    background: #428bca;
    color: white;
}
.uif-sub-breadcrumb {
    position: absolute;
    top: -9999em;
    background: #f2f2f2;
    padding: 0;
    margin: 0;
    width: 175px;
}
.uif-sub-breadcrumb.open {
    top: auto;
    right: 0;
    margin-top: 2px;
    margin-right: -87.5px;
}
.uif-sub-breadcrumb li a {
   padding: 4px;
}

JavaScript (this is all custom stuff; feel free to adapt)

$(document).ready(function() {
    var w = $(window),
        c = $('#path-based.uif-breadcrumb'),
        b = $('#path-based.uif-breadcrumb .breadcrumb'),
        l = $('#path-based.uif-breadcrumb .breadcrumb li'),
        e = '<li class="uif-breadcrumb-more"><button type="button" class="btn btn-link btn-xs" aria-label="Expand breadcrumb"> ... </button></li>',
        f = '<li class="uif-breadcrumb-close"><button type="button" class="btn btn-link" aria-label="Collapse breadcrumb">Close</button></li>',
        z = false;
    
    function collapse_breadcrumb() {
        l.not(':first').not(':last').each(function() {
            var count = l.length;
            if (3 > count.length) {
                return;
            }
            $(this).hide();
            if (z) return;
            $('#path-based.uif-breadcrumb .breadcrumb li:first').append(e);
            z = true;
        });
    }
    
    function expand_breadcrumb() {
        l.not(':first').not(':last').each(function() {
            $(this).show(); 
        });
        z = false;
        $('#path-based.uif-breadcrumb .breadcrumb .uif-breadcrumb-more').remove();
    }
    
    function open_breadcrumb() {
        b.addClass('open');
        l.not(':first').not(':last').each(function() {
            $(this).show(); 
        });
        b.append(f);
    }
    
    function close_breadcrumb() {
        b.removeClass('open');
        l.not(':first').not(':last').each(function() {
            $(this).hide(); 
        });
        if (z) return;
        $('#path-based.uif-breadcrumb .breadcrumb li:first').append(e);
        z = true;
    }
    
    $('#path-based.uif-breadcrumb').on('click', '.uif-breadcrumb-more button', function() {
        $(this).parent().hide();
        $('.uif-breadcrumb-close').parent().show();
        open_breadcrumb();
    });
    
    $('#path-based.uif-breadcrumb').on('click', '.uif-breadcrumb-close button', function() {
        $(this).parent().hide();
        $('.uif-breadcrumb-more').show();
        close_breadcrumb();
    });
    
    $('.uif-sub-expand').click(function() {
        if ($(this).next().hasClass('open')) {
            $(this).next().removeClass('open').attr('aria-expanded', 'false').attr('aria-hidden', 'true');
            $(this).find('span').addClass('icon-angle-down').removeClass('icon-angle-up');
        } else {
            $(this).next().addClass('open').attr('aria-expanded', 'true').attr('aria-hidden', 'false');
            $(this).find('span').removeClass('icon-angle-down').addClass('icon-angle-up');
            $(this).next().find('li:first a').focus();
        }
    });
    if (768 >= $(window).width()) {
        collapse_breadcrumb();
    }
    
    w.resize(function() {
        if (768 >= $(window).width()) {
            collapse_breadcrumb();
        } else {
            expand_breadcrumb();
            if (b.hasClass('open')) {
                close_breadcrumb();
                $('.uif-breadcrumb-close').remove();
            }
        }
    });
});

Accessibility Considerations

As with all things in Kuali interfaces, breadcrumbs must meet WCAG level A and AA criteria. This means that:

  • Links should navigate somewhere and be announced clearly; they should indicate what the link is and where it goes
  • Buttons should be used to expand and collapse menus rather than links, and they should be focusable
  • When opening and closing a menu, make sure you update the appropriate ARIA prop's or attr's using JavaScript. For example, when a submenu is collapsed, it should have the property aria-expanded="false". When it's opened that property should change to true.
  • Closing a submenu should send focus back to its parent item.

Accessibility Resources

As always, use valid, semantic, proper HTML markup to optimize accessibility.

W3 HTML Validator
WebAim WAVE 

Keyboard Shortcuts

None out of the ordinary.

Research and Discussion

None at this time.