Consider the following sample code
<body>
<nav>
<a href="#s1">First Section</a>
<a href="#s2">Section 2</a>
</nav>
<main>
<section id="s1">
<p>Example paragraph
<p>Paragraph 2
</section>
<section id="s2">
<p>Example paragraph
<p>Paragraph 2
</section>
</main>
</body>
I can select the section
that is selected with
section {
background: #fff;
}
section:target {
background: #f00;
}
But I want to target the a
that selected it using only HTML/CSS, which I could imagine being like
a[href=:target] {
font-weight: bold;
}
or
a:target(href) {
font-weight: bold;
}
The only solution I could come up with is
HTML:
<body>
<div id="s1"><div id="s2">
<nav>
<a href="#s1">First Section</a>
<a href="#s2">Section 2</a>
</nav>
<main>
<section name="s1">
<p>Example paragraph
<p>Paragraph 2
</section>
<section name="s2">
<p>Example paragraph
<p>Paragraph 2
</section>
</main>
</div></div>
</body>
CSS:
#s1:target a[href="#s1"],
#s2:target a[href="#s2"] {
font-weight: bold;
}
section {
background: #fff;
}
#s1:target section[name="s1"],
#s2:target section[name="s2"] {
background: #f00;
}
I don't like this, however, because it introduces needless elements (the div
s to target).
Is there a clean way to do this without JavaScript?
How it works: 1 First, select the <ul> element by its id using the querySelector () method. 2 Second, create a new document fragment. 3 Third, for each element in the languages array, create a list item element, assign the list item’s innerHTML to the... 4 Finally, append the document fragment to the <ul> element. More ...
This page will explain the most basic CSS selectors. The element selector selects HTML elements based on the element name. The id selector uses the id attribute of an HTML element to select a specific element.
If the selector matches an ID and this ID is erroneously used several times in the document, it returns the first matching element. If the selectors specified in parameter are invalid a DOMException with a SYNTAX_ERR value is raised.
The DocumentFragment.querySelector () method returns the first element, or null if no matches are found, within the DocumentFragment (using depth-first pre-order traversal of the document's nodes) that matches the specified group of selectors.
While the :target
pseudo-class exists for matching a named anchor or an element with an ID corresponding to the current URL fragment, CSS does not provide a selector for matching links that point to the current URL fragment.
There is no clean way to do this without JavaScript. I would heavily prefer using JavaScript over polluting the markup with unsemantic elements and invalid attributes for the sake of accommodating CSS (section
elements cannot have name
attributes).
The hashchange
event is well-supported, so if you can afford it it's simply a matter of listening for that event and toggling a class on the right element:
var navLinks = document.querySelectorAll('nav > a');
window.onhashchange = function() {
for (var i = 0; i < navLinks.length; i++) {
if (navLinks[i].href.match(/(#.*)/)[1] == window.location.hash) {
navLinks[i].className = 'selected';
} else {
navLinks[i].className = '';
}
}
};
var navLinks = document.querySelectorAll('nav > a');
window.onhashchange = function() {
for (var i = 0; i < navLinks.length; i++) {
if (navLinks[i].href.match(/(#.*)/)[1] == window.location.hash) {
navLinks[i].className = 'selected';
} else {
navLinks[i].className = '';
}
}
};
section {
background: #fff;
}
section:target {
background: #f00;
}
a.selected {
font-weight: bold;
}
<nav>
<a href="#s1">First Section</a>
<a href="#s2">Section 2</a>
</nav>
<main>
<section id="s1">
<p>Example paragraph
<p>Paragraph 2
</section>
<section id="s2">
<p>Example paragraph
<p>Paragraph 2
</section>
</main>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With