<figure>
<img
id="ireland-team"
src="img/republic-of-ireland-team.webp"
alt="The Republic of Ireland national football team taken before the FIFA World Cup qualification 2014 match against Austria on 2013-09-10"
width="1280"
height="850"
>
<figcaption>
<div>
<span>Back row:</span>
<ol>
<li><label><input type="checkbox" name="players" onclick="onlyOne(this)" data-src="player1">18. Anthony Pilkington</label></li>
<li><label><input type="checkbox" name="players" onclick="onlyOne(this)" data-src="player2">3. Marc Wilson</label></li>
<li><label><input type="checkbox" name="players" onclick="onlyOne(this)" data-src="player3">1. David Ford</label></li>
<li><label><input type="checkbox" name="players" onclick="onlyOne(this)" data-src="player4">10. Robbie Keane</label></li>
<li><label><input type="checkbox" name="players" onclick="onlyOne(this)" data-src="player5">5. Richard Dunne</label></li>
<li><label><input type="checkbox" name="players" onclick="onlyOne(this)" data-src="player6">4. John O'Shea</label></li>
</ol>
</div>
<div>
<span>Front row:</span>
<ol>
<li><label><input type="checkbox" name="players" onclick="onlyOne(this)" data-src="player7">8. James MacCarthy</label></li>
<li><label><input type="checkbox" name="players" onclick="onlyOne(this)" data-src="player8">2. Seamus Coleman</label></li>
<li><label><input type="checkbox" name="players" onclick="onlyOne(this)" data-src="player9">13. Jon Walters</label></li>
<li><label><input type="checkbox" name="players" onclick="onlyOne(this)" data-src="player10">15. Paul Green</label></li>
<li><label><input type="checkbox" name="players" onclick="onlyOne(this)" data-src="player11">9. Shane Long</label></li>
</ol>
</div>
</figcaption>
</figure>
img {
width: 100%;
height: auto;
clip-path: circle(200% at 50% 50%);
transition: clip-path 0.6s ease-in-out;
}
.player1 {
clip-path: circle(6% at 23% 27%);
}
.player2 {
clip-path: circle(6% at 32.5% 26%);
}
.player3 {
clip-path: circle(6% at 42.75% 24%);
}
.player4 {
clip-path: circle(5% at 54.5% 28%);
}
.player5 {
clip-path: circle(6% at 66.5% 24%);
}
.player6 {
clip-path: circle(6% at 77% 23%);
}
.player7 {
clip-path: circle(6% at 20.5% 54%);
}
.player8 {
clip-path: circle(6% at 35.5% 54%);
}
.player9 {
clip-path: circle(6% at 46.5% 54%);
}
.player10 {
clip-path: circle(6% at 59% 55%);
}
.player11 {
clip-path: circle(6% at 74% 52.5%);
}
figure {
max-width: 900px;
}
figcaption {
font-size: 0.85rem;
border-block-end: 1px solid rgba(128, 128, 128, 0.5);
div {
margin-block-end: 0.5rem;
}
}
ol {
display: inline;
list-style-type: none;
padding: 0;
margin-block-end: 0.5rem;
li {
display: inline;
&:not(:last-of-type):after {
content: ",";
padding-inline-end: 0.25rem;
}
&:last-of-type:after {
content: ".";
}
}
}
input[type="checkbox"],
label {
cursor: pointer;
}
/* general */
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: "Trebuchet MS", "Lucida Sans Unicode", "Lucida Grande",
"Lucida Sans", Arial, sans-serif;
display: grid;
justify-content: center;
}
const checkboxes = document.querySelectorAll("input[name='players']");
let img = document.getElementById("ireland-team");
checkboxes.forEach((checkbox) => {
checkbox.addEventListener("click", (event) => {
if (event.target.checked) {
unfocusPlayers();
focusPlayer(event.target);
} else {
unfocusPlayers();
}
});
});
function onlyOne(checkbox) {
let checkboxGroup = document.getElementsByName(checkbox.name);
checkboxGroup.forEach((item) => {
if (item !== checkbox) item.checked = false;
});
}
function focusPlayer(el) {
let playerId = el.getAttribute("data-src");
img.classList.add(playerId);
}
function unfocusPlayers() {
img.setAttribute("class", "");
}
I wanted to provide the ability to identify a player in a team line-up photo. If you click on the player’s name, the photo is clipped to just their face to give focus like a spotlight in a theatrical performance!
I noticed that other solutions highlighted a player only when a cursor hovers over the photo. This limits the functionality to desktop. I wanted a solution that works on all devices. This is why I chose a series of checkboxes as the input method.
The clip-path
property is used to cut the photo down to the face of a player. I manually found the correct coordinates for each player’s face using the browser’s devtools. Coupling this with the transition
property creates a smooth effect.
JavaScript is used to apply a class with a clip path to the image when a checkbox is checked. Since HTML does not have the concept of an exclusive checkbox group, I ensure that only one checkbox is checked at a time with a click handler.
The photo is from Wikimedia Commons and is licensed under the Creative Commons Attribution-Share Alike 3.0 Austria license.