Highlighting text in React using hover effects on list elements

Imagine having HTML / JSX structured like this:

<ul>
  <li>First point in list</li>
  <li>Second point in list</li>
</ul>

and the goal is to highlight a contiguous range that spans multiple list items:

<ul>
  <li>First <mark>point</mark></li>
  <li><mark>Second point</mark></li>
</ul>

Furthermore, there's a desire to implement behavior where hovering over one <mark> tag triggers an effect on another <mark> tag. This should give the user a seamless experience as if it were a single <mark> tag.

Is it achievable solely with CSS / Tailwind? As per current knowledge, using the sibling ~ combinator mentioned here, only affects elements that appear later not earlier. The same limitation seems to apply to the peer class in Tailwind.

If JavaScript intervention becomes necessary, can anyone provide guidance or resources? Noting this pertains to a React project, manipulating the DOM directly might involve certain considerations.

Answer №1

  1. When hovering over one mark hovers all others, it's a simple has() call.

ul:has(mark:hover) mark {
  background-color: red;
}
<ul>
  <li><span>First bullet </span><mark>point</mark></li>
  <li><mark>Second bullet</mark><span> point</span></li>
  <li><span>Third bullet </span><mark>point</mark></li>
  <li><mark>Fourth bullet</mark><span> point</span></li>
  <li><span>The </span><mark>Fifth bullet</mark><span> point</span></li>
</ul>

  1. If hovering over a mark only hovers contiguous marks, then it requires more complex styling.

li mark:hover,
li:has(mark:last-child:hover) + li > mark:first-child,
li:has(mark:last-child):has(+ li > mark:first-child:hover) mark {
  background-color: red;
}
<ul>
  <li><span>First bullet </span><mark>point</mark></li>
  <li><mark>Second bullet</mark><span> point</span></li>
  <li><span>Third bullet </span><mark>point</mark></li>
  <li><mark>Fourth bullet</mark><span> point</span></li>
  <li><span>The </span><mark>Fifth bullet</mark><span> point</span></li>
</ul>

  1. To work around Firefox not supporting :has() by default (as of v109), JavaScript can be used.

const ul = document.querySelector("ul");

const removeActive = function (evt) {
  const active = evt.currentTarget.querySelector("mark.active");
  if (active) active.classList.remove("active");
}

ul.addEventListener("mouseover", function (evt) {
  removeActive(evt);
  let elem = null;

  const mark = evt.target.closest("mark");
  if (!mark) return;
  
  const li = mark.closest("li");
  
  if (!mark.previousSibling) {
    const prevLi = li.previousElementSibling;
    elem = prevLi && prevLi.lastChild;
  } else if (!mark.nextSibling) {
    const nextLi = li.nextElementSibling;
    elem = nextLi && nextLi.firstChild;
  }
  
  if (elem && elem.nodeName == "MARK") {
    elem.classList.add("active");
  }
});

ul.addEventListener("mouseleave", removeActive);
li mark:hover,
li mark.active {
  background-color: red;
}
<ul>
  <li>First bullet <mark>point</mark></li>
  <li><mark>Second bullet</mark> point</li>
  <li>Third bullet <mark>point</mark></li>
  <li><mark>Fourth bullet</mark> point</li>
  <li>The </span><mark>Fifth bullet</mark><span> point</li>
</ul>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The data type 'string' cannot be assigned to the data type 'undefined'

These are the different types available: export type ButtonProperties = { style?: 'normal' | 'flat' | 'primary'; negative?: boolean; size?: 'small' | 'big'; spinner?: boolean; } export type ...

A guide to submitting forms within Stepper components in Angular 4 Material

Struggling to figure out how to submit form data within the Angular Material stepper? I've been referencing the example on the angular material website here, but haven't found a solution through my own research. <mat-horizontal-stepper [linea ...

Stop text from being selected across all browsers in Firefox

My current CSS includes: *{ -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } If you visit http://jsfiddle.net/KyF5x/ and click be ...

How can Angular CLI prevent the submission of an HTML form unless a previous option has been selected

I am currently working on a form that contains select fields with various options pre-populated. <form [formGroup]="selectVehicleForm"> <select formControlName="Manufacturer"> <option *ngFor='let ...

The content within the mat-card-content paragraph exceeds the boundaries of the mat-card container,

I recently began working with Angular Material and came across an issue. When I have a shorter text paragraph, it overflows the card. However, when I use a larger paragraph, the text wraps nicely. Here is the code snippet: <mat-card *ngFor="let s ...

Is it possible for a mobile device to play .ogg videos?

Currently, I am setting up a server to stream videos using HTML. So far, I have tested playing both .mp4 and .ogg video formats on my computer successfully. However, when I attempted to play the same videos on a mobile device, only the .mp4 file showed u ...

Combining multiple 'Eithers' and 'Promises' in fp-ts: A guide to piping and chaining operations

Recently, I began working with fp-ts and wanted to create a method with functional-like behavior that would: Parse a bearer token Verify the validity of the user using the parsed token import { Request } from 'express'; import { either } from & ...

Prevent Image Distortion in HTML and CSS

Is there a way to prevent a background image from stretching in html/css? Take a look at the current code below, where the image behind a button appears like this: #backImage6{ /*@editable*/background-image:url(https://images.unsplash.com/phot ...

How can I replicate the functionality of a div mimicking a select element using javascript upon clicking away from the element?

My task was to design a pseudo-select element that showcases columns for each row within the select. Due to HTML's restriction on allowing the <option> tag to include HTML, I had to find an alternate solution. One issue I encountered was replic ...

Ways to deactivate a button within a Kendo Grid cell

I am trying to include 2 buttons in a cell, where one button calls a specific function and the other button disables the previous button that calls the function. In my template column, I have implemented the following: return '<button kendo-button ...

The added class is not being successfully applied to the ClassList

I'm currently working on a page where I want the colors of a button and the background to switch when the button is clicked. document.querySelector("body.light").classList.toggle("dark"); document.querySelector("button.dark").classList.toggle("light" ...

Does deploying on Heroku cause Material UI makeStyles to disappear?

After deploying to Heroku, I noticed that all my MUI makeStyles calls are being removed, causing a major issue with the appearance of my app. Before resorting to inline styling (which I tested and confirmed works), I wanted to seek advice on this matter. ...

The edges of the cube are not joined together

Looking for a 3D transform cube that can freely flip left and right, with the button fitting into it perfectly. I've found the CSS code to achieve this, but when I set the width of the ".cube" below 200px, the borders of the cube don't connect. I ...

Setting a specific time zone as the default in Flatpickr, rather than relying on the system's time zone, can be

Flatpickr relies on the Date object internally, which defaults to using the local time of the computer. I am currently using Flatpickr version 4.6.6 Is there a method to specify a specific time zone for flatpickr? ...

Undefined React custom hooks can be a tricky issue to troub

Just delving into the world of React and trying to wrap my head around custom hooks, but I keep hitting roadblocks. Here's the latest hurdle that I'm facing, hoping for some guidance. I'm taking a step-by-step approach to creating a functio ...

The ideal login page design

I apologize for my lack of knowledge in React, but I am quite new to it and have been struggling with this issue for days. I am having trouble creating a login page in ReactJS. Here is the code in my app.js: import React from 'react'; import {Ha ...

Tips for running two elixir tasks consecutively?

Check out this piece of code: var gulp = require('gulp'), fs = require('fs'); gulp.task('taskOne', function() { return gulp.src('folder1/file1.js') .pipe(gulp.dest('folder2')); }); gulp.t ...

Issue with React Redux: Store dispatch not causing component update

I have recently implemented React Redux in my project, but I seem to be encountering some issues. Despite changing the state, the value remains the same. I attempted to use useStore(), but it does not take any parameters. Can anyone provide insight into wh ...

Transform the assurance into a JSON entity

Currently facing an issue with converting the promise returned by the service to the controller. My goal is to generate an array of JSON objects using the data within the promise. In the controller, this is what I'm receiving: https://i.stack.imgur.co ...

What could be the reason for my ng-init not functioning properly?

<body ng-init="user=${userID};month=${month};curPageNum=${currentPage}"> Using JSP, I set initial values in the body tag. However, in the controller, I have the following code: console.debug($scope.user + " "+$scope.month} The issue is that only ...