This page compares two ways of jumping to a specific area further down a page: the CSS :target pseudo-class on its own, and the same pattern enhanced with JavaScript.
The key difference is not visual, both examples scroll the target into view and apply the same highlight. The difference is whether keyboard focus actually moves to the target, or only the scroll position changes.
:target onlyThis example relies entirely on native browser fragment navigation and the :target pseudo-class. No JavaScript is involved.
Important: native fragment navigation scrolls the target into view, but it does not move keyboard focus there. After activating the link below, pressing Tab will move focus to whatever is next in the document after the link, not to the target area itself. This is a common misconception, adding tabindex="-1" to a target on its own does not fix this either, focus only moves if something explicitly calls .focus() on the target.
Click the link below to see an example:
Pri at epicurei convenire, ut oratio liberavisse est. Ex his dolorum concludaturque, et mel solet soleat accumsan. In mollis ancillae intellegebat has. Sea congue cetero cu, ut mnesarchum vituperatoribus mel. Ne vix solet dicant possit, eos solet dictas facilisi ei.
Vel ei quaeque definiebas. Ius no assum impedit. Ipsum efficiendi usu ei. Prima electram principes in pro, id pro dolores appellantur, at causae admodum voluptatum eam. Accusam percipit erroribus pro et. Brute option usu cu, alia enim mutat eum cu.
His vocent integre mnesarchum no, ex prompta sapientem nec, te complectitur disputationi nam. Per an laudem convenire instructior, est graece labore moderatius eu, te natum verterem nam. Soleat doming splendide et has. Usu in aperiam albucius expetendis, integre tacimates quo at. Ad quo iuvaret deleniti copiosae, in vix ipsum dicant, sint consequuntur eu has. Ex pri solum graecis deterruisset, qui enim saperet iracundia ei.
Ut vix facete labitur deserunt, possim vocent debitis ex sed. An usu vidisse copiosae petentium. Debet virtute te vel. Mutat ullum molestie eos ex. Causae facilis oportere ius at, in sint ceteros vix. Ne brute convenire vituperata nec.
Id his similique philosophia, ne exerci aliquando similique has. His id antiopam salutandi forensibus. Singulis intellegebat in pro, vim illud postulant constituam eu. Ad vim wisi inani commune.
<a href="#target1">Link to target</a>
...
<div id="target1">
Hello world
</div>
<style>
:target {
outline: 2px solid #C87D00;
animation: fade 5s forwards;
}
</style>
Pri at epicurei convenire, ut oratio liberavisse est. Ex his dolorum concludaturque, et mel solet soleat accumsan. In mollis ancillae intellegebat has. Sea congue cetero cu, ut mnesarchum vituperatoribus mel. Ne vix solet dicant possit, eos solet dictas facilisi ei.
Vel ei quaeque definiebas. Ius no assum impedit. Ipsum efficiendi usu ei. Prima electram principes in pro, id pro dolores appellantur, at causae admodum voluptatum eam. Accusam percipit erroribus pro et. Brute option usu cu, alia enim mutat eum cu.
:target plus JavaScriptThis example uses the same visual highlight, but adds JavaScript to explicitly move keyboard focus to the target as well, not just scroll to it.
tabindex="-1", making it programmatically focusable without adding it to the normal tab order.hashchange event. When the fragment changes to #target2, it finds that element and calls .focus() on it directly.#target2 (for example, from a bookmark or another page), rather than only reacting to a click during the current visit.Without this script, a keyboard user who activates the link would have their view scrolled to the target, but their actual keyboard focus would remain on the link, or jump to whatever happens to be next in the document. Pressing Tab afterwards would not continue naturally from the target area, it would continue from wherever focus was actually left, which can feel disorienting and unpredictable. Moving real focus to the target keeps the visual scroll position and the keyboard user's actual position in the document in sync.
Note: this is the same underlying technique demonstrated on the focus management testing page, applied here to in-page fragment links rather than a multi-step single page app.
Click the link below to see an example:
Link to target (CSS + JavaScript)
Pri at epicurei convenire, ut oratio liberavisse est. Ex his dolorum concludaturque, et mel solet soleat accumsan. In mollis ancillae intellegebat has. Sea congue cetero cu, ut mnesarchum vituperatoribus mel. Ne vix solet dicant possit, eos solet dictas facilisi ei.
Vel ei quaeque definiebas. Ius no assum impedit. Ipsum efficiendi usu ei. Prima electram principes in pro, id pro dolores appellantur, at causae admodum voluptatum eam. Accusam percipit erroribus pro et. Brute option usu cu, alia enim mutat eum cu.
His vocent integre mnesarchum no, ex prompta sapientem nec, te complectitur disputationi nam. Per an laudem convenire instructior, est graece labore moderatius eu, te natum verterem nam. Soleat doming splendide et has. Usu in aperiam albucius expetendis, integre tacimates quo at. Ad quo iuvaret deleniti copiosae, in vix ipsum dicant, sint consequuntur eu has. Ex pri solum graecis deterruisset, qui enim saperet iracundia ei.
Ut vix facete labitur deserunt, possim vocent debitis ex sed. An usu vidisse copiosae petentium. Debet virtute te vel. Mutat ullum molestie eos ex. Causae facilis oportere ius at, in sint ceteros vix. Ne brute convenire vituperata nec.
Id his similique philosophia, ne exerci aliquando similique has. His id antiopam salutandi forensibus. Singulis intellegebat in pro, vim illud postulant constituam eu. Ad vim wisi inani commune.
Vel ei quaeque definiebas. Ius no assum impedit. Ipsum efficiendi usu ei. Prima electram principes in pro, id pro dolores appellantur, at causae admodum voluptatum eam. Accusam percipit erroribus pro et. Brute option usu cu, alia enim mutat eum cu.
<a href="#target2" id="js-target-link">Link to target</a>
...
<div id="target2" tabindex="-1">
Hello world
</div>
<script>
function focusTarget2() {
if (window.location.hash === '#target2') {
var target = document.getElementById('target2');
if (target) {
target.focus();
}
}
}
// Handle direct arrival at #target2 (bookmark, external link, page load)
focusTarget2();
// Handle activation of the link during the current page visit
window.addEventListener('hashchange', focusTarget2);
</script>
Pri at epicurei convenire, ut oratio liberavisse est. Ex his dolorum concludaturque, et mel solet soleat accumsan. In mollis ancillae intellegebat has. Sea congue cetero cu, ut mnesarchum vituperatoribus mel. Ne vix solet dicant possit, eos solet dictas facilisi ei.
Vel ei quaeque definiebas. Ius no assum impedit. Ipsum efficiendi usu ei. Prima electram principes in pro, id pro dolores appellantur, at causae admodum voluptatum eam. Accusam percipit erroribus pro et. Brute option usu cu, alia enim mutat eum cu.