htmlcsscss-positionabsolutetabindex

Tab-Index for absolutely positioned elements in layout


Tab Index for Absolute-Position Elements

For the time being, lets assume I wrote the code below:

    <header class="header hap" [ngClass]="authority">
        <div class="header-inner">
            <div class="header-identity">
                <a id="theLogo" class="logo" [routerLink]="[links.home]" title="Navigate to Home">
                    <img src="assets/logo-white.svg" alt="Logo">
                </a>
                <span class="client-logo" *ngIf="user.brandingImage && !user.isTheAdmin()">
                    <img class="brandingImage" [src]="user.brandingImage" [alt]="user.brandingName" onerror="this.style.display='none'">
                </span>
                [ more links ]
            </div>
            <nav class="main-nav for authenticated" [ngClass]="{'active':showMenu, 'app-only':!isCurrPageAdminApp()}">
                <button class="menu" (click)="toggleMenu()">Menu</button>
                <div class="main-nav-flyout" *ngIf="showMenu">
                    <div class="nav-header">
                        <ul>
                            <li>
                                <a id="main-nav-profile" [routerLink]="['/profile']"><span class="icon icon-user2"></span> My Profile</a>
                            </li>
                            [ more dropdown items ]
                        </ul>
                        <a id="main-nav-close" class="close"(click)="onClickMenuClose()"><span class="icon-cross"></span></a>
                    </div>
                    <div class="nav-body">
                        <ul *ngIf="isCurrPageAdminApp()" class="main-nav-list">
                            <li class="current-app">Administrative Tools</li>
                            <li><a id="main-nav-xAdmin" *ngIf="user.isTheAdmin()" [routerLink]="['admin/x']">X Admin</a></li>
                            [ more links ]
                            <li>
                                <span>Reports</span>
                                <ul>
                                    <li class="user-status"><a id="main-nav-userStatusReport" [routerLink]="['admin/reports/userStatus']">User Status</a></li>
                                    [ more links ]
                                </ul>
                            </li>
                        </ul>
                        <ul class="app-list" *ngIf="user.userApplications">
                            <li *ngIf="showTheLink()">
                                <a id="app-list-type" [routerLink]="['/']">
                                    ...
                                </a>
                            </li>
                            [ more links ]
                            <li *ngFor="let application of user?.userApplications">
                                <a id="app-list-{{application.abbreviation}}" *ngIf="!isAdminApp(application)" (click)="onClickMenuItem(application)">
                                    {{ application.title }}
                                </a>
                            </li>
                        </ul>
                    </div>
                </div>
            </nav>
            <nav class="user-nav for authenticated" role="menu">
                <span *ngIf="user.brandingName" class="user-location">{{user.brandingName}}</span>
                <span *ngIf="user.brandingName" class="pipe">|</span>
                <a id="user-nav-profile" class="user-name" [routerLink]="['/profile']">
                    <span class="name">{{user?.firstName}} {{user?.lastName}}</span>
                </a>
                <a id="user-nav-logout" class="logout" [routerLink]="['/', 'logout']">Log out</a>
            </nav>
        </div>
    </header>

Issue

Various elements -- probably .header-inner > * -- are styled using position: absolute;, so the tabindex-order is skewed for elements which are declared later in the markup but positioned geometrically earlier in the layout.

Question

Is there a way to force the tabindex to be, say, all natural indices (0) except for 2 items that need to be switched -- in a scalable way while not having to implement tabindex for every new item in the layout?


Solution

  • The short answer is no, it's not possible to switch only two elements without at least adding tabindex to every element in the flow that has to be focused before those two elements.

    All elements with positive tabindex will be focused first in an incremental way, or in their source order if they have the same value, and all elements with default value or zero will be focused last.

    So if you have 6 focusable elements and you want to have elements 5 and 6 to be focused after elements 1 and 2, you need something like this:

    <input type="text" tabindex="1">1</input>
    <input type="text" tabindex="1">2</input>
    <input type="text">3</input>
    <input type="text">4</input>
    <input type="text" tabindex="1">5</input>
    <input type="text" tabindex="1">6</input>
    

    In general having the source order match the flow is the easiest way to make it work.

    There is one particular case that is simpler. If the elements you want to move happen to be the first elements that need focus on your page, then in that particular case you can put the tabindex only on those elements.

    For instance, if we wanted elements 5 and 6 be the first elements on the page, and everything else after them, all you need to do is this:

    <input type="text">1</input>
    <input type="text">2</input>
    <input type="text">3</input>
    <input type="text">4</input>
    <input type="text" tabindex="1">5</input>
    <input type="text" tabindex="1">6</input>
    

    So in general, if the elements you want to change order are in the header, and they are the first things that should be focusable on your page, it should be easy to rearrange them and let the rest of the page flow naturally.

    If the elements had to be last you are out of luck, you should either: