Choose the CSS siblings located between two specific elements

The code in the HTML I'm viewing appears as follows:

document.querySelectorAll('h4#unique_id  ~ h5 ~p +p +h5').forEach(title => console.log(title))
<body>
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <!-- selection should start here -->
    <h5>title text 1</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 2</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 3</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
  <!-- and end here -->
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</body>

I aim to extract all the h5 elements, along with the p elements if possible.

My current attempt using

document.querySelectorAll('h4#unique_id  ~ h5 ~p +p +h5')
misses the first desired h5 element and includes the last unwanted one. I am struggling with sibling selectors and how to utilize :not or similar functions to halt when encountering another h4.

This query is based on jquery which isn't accessible to me, while another solution assumes knowledge of the precise number and position of elements – something I lack. (Select elements between two defined elements)

Can this task be accomplished solely through CSS selectors?

Answer №1

If you want to style specific elements based on their relationship with another element, you can use a combination of sibling selectors and the not pseudo-class:

The selector looks like this:

#unique_id~p:not(#unique_id~h4~p) /* select any p following the unique id but not a p following another h4 after the unique id */

You can then apply the same concept for your h5 elements using this code snippet:

document.querySelectorAll('#unique_id~p:not(#unique_id~h4~p),#unique_id~h5:not(#unique_id~h4~h5)').forEach(title => title.style.color = 'red');
<h4 id="unique_id"> foo bing bar </h4>
<p>some text</p>
<p>some text</p>
... (additional content)
<h5>title text I don't want</h5>
<p>some text I don't want</p>

In response to your edit request - excluding the p before the first h5 element, here's a modified selector based on Alohci's suggestion:

document.querySelectorAll('#unique_id~:is(h5, h5~p):not(#unique_id ~ h4 ~ *)').forEach(title => title.style.color = 'red');
<h4 id="unique_id"> foo bing bar </h4>
<p>some text</p>
<p>some text</p>
... (additional content)
<h5>title text I don't want</h5>
<p>some text I don't want</p>

Answer №2

Quite an intriguing query you have there. If my comprehension serves me right, your aim is to capture and log all the elements that don't include certain text I wish to avoid as well as the h5 elements.

If there exists a parent element, you can leverage the > selector in conjunction with the parent element to target all of its children using the * selector.

It's possible to apply multiple :not() selectors within a statement. Below, I simply picked out all the p and h4 elements preceded by the h4#randome_id_234353 element, like this:

document.querySelectorAll('.container > *:not(h4#randome_id_234353 ~ p):not(h4#randome_id_234353 ~ h5):not(h4)').forEach(title => console.log(title))
<body>
<div class="container">
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 1</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 2</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 3</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</div>
</body>

If a container isn't present, you can employ the same technique to log everything that does not come before h4#randome_id_234353.

document.querySelectorAll('h4#unique_id ~ *:not(h4#randome_id_234353 ~ *):not(h4#randome_id_234353').forEach(title => console.log(title))
<body>
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 1</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 2</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 3</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</body>

Answer №3

There are only a few array methods that work with array-like objects, so I often convert a NodeList (which is an iterable, array-like object but not an actual array) into an array to have more options for manipulation.

By converting the NodeList into an array, I can utilize the javascript method .filter() which allows me to remove unwanted elements from the collection easily.


Converting a NodeList to an array:

How can I transform this static NodeList:

let myClassElements = document.querySelectorAll('.myclass');

into an array?

I can achieve this by combining spread syntax (...) with an array literal ([]):

let myClassElements = [... document.querySelectorAll('.myclass')];

Based on that approach, I am able to create an array containing all the necessary elements (and some unnecessary ones):

[...document.querySelectorAll('h4#unique_id ~ h5, h4#unique_id ~ p')]

as well as another array specifically for the unnecessary elements:

[...document.querySelectorAll('h4:not(#unique_id) ~ h5, h4:not(#unique_id) ~ p')]

Then, I can use the .filter() method to filter out the unnecessary elements from the main array:

const rawListOfElements = [...document.querySelectorAll('h4#unique_id ~ h5, h4#unique_id ~ p')];

const elementsToRemove = [...document.querySelectorAll('h4:not(#unique_id) ~ h5, h4:not(#unique_id) ~ p')];

const mySelectedElements = rawListOfElements.filter((element) => !elementsToRemove.includes(element)).forEach(title => console.log(title));

Example in Action:

const rawListOfElements = [...document.querySelectorAll('h4#unique_id ~ h5, h4#unique_id ~ p')];

const elementsToRemove = [...document.querySelectorAll('h4:not(#unique_id) ~ h5, h4:not(#unique_id) ~ p')];

const mySelectedElements = rawListOfElements.filter((element) => !elementsToRemove.includes(element)).forEach(title => console.log(title));
<body>
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <!-- selection should start here -->
    <h5>title text 1</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 2</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 3</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
  <!-- and end here -->
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</body>

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

Tips for incorporating transitions into CSS styling

After successfully adding a picture over an element when hovering over it, I decided to include a transition: 0.2s; property but unfortunately the transition effect is not working as expected. Why is this happening? My intention is for the picture to smoot ...

The Passport with the name "Hello World" never succeeds

I have the following: import {Router} from 'express'; import passport from 'passport'; import {Strategy} from 'passport-local'; import pg from 'pg'; import {pgUri} from '../environment'; let loginRouter = ...

Exploring the documentation of node.js with doxygen

When it comes to my C projects, I make sure to document them using Doxygen. Recently, I delved into the world of NodeJs and attempted to document .js files with Doxygen, but unfortunately, no output was generated. Despite my efforts to search for answers ...

I wish to have the sidebar shown initially, then be able to collapse it by clicking a button and adding a dropdown feature to the side of the menu items using Bootstrap

I am looking to implement a sidebar menu using Bootstrap. I want the ability to hide the menu, even on larger screens, by clicking a button. When collapsing the menu to the left side, I want the icons to display on the left as well. Clicking on a menu i ...

Positional Error Found in Bootstrap Popover Arrow

I'm having an issue with the Bootstrap Popover Tooltip. Can anyone explain why the arrow is not formatting correctly? <div style="display:inline-block;"> <a id="pop" href="#" data-toggle="popover" data-content="<%= user.experience.de ...

``Incorporating flowplayer with autoplay set to true has proven to be ineffective

Is there a way to get my PHP website to automatically play videos using flowplayer? I'm having trouble getting it to work and no errors are being shown. $(function(){ // Top Stories videos var topStoriesVideos = [ { so ...

Looking for a jQuery plugin that creates a sticky top menu bar?

I am in search of a jQuery plugin (or code/guide) that can achieve this effect: Unfortunately, this particular one is not available for free Please take note that the navigation bar does not initially appear at the top but sticks once the viewport reache ...

Using arrow keys and return to effortlessly navigate through text input fields

Currently, I am working on developing a jQuery-based navigation system for switching between multiple input fields. The first part of the code is functioning correctly, allowing users to navigate downwards using either the down arrow or the return key. H ...

Elements within the DIV tag are not displaying in a linear arrangement as intended

I'm having trouble creating a navbar with Bootstrap 4. The items in my div tag are not inline, and I can't align my nav item to the right. Here is the HTML code: <nav class="navbar navbar-inverse "> <div style="display:inline"> ...

Designing Games with Matrix Elements

Greetings to the StackOverflow Community! Currently, I am working on developing a JavaScript version of the well-known game Pentago as a personal side project before resuming my studies in the fall. However, I have hit a roadblock and need some guidance o ...

When you start scrolling down, the JavaScript menu will cleverly disappear, only to re

I am facing an issue with my menu, which is a normal block-displayed div. There is another div with annotation above it. I want the menu to stick to the top as fixed when scrolling down, but immediately hide itself. The goal is for the menu to appear when ...

What are the steps for utilizing the map function to merge an array or nested array into a div element?

I'm currently developing a recipe box application and have shared the code pen for it: http://codepen.io/capozzic1/pen/gmpVyr?editors=0110. The code snippet is as follows: class RecipeList extends React.Component { constructor(props) { super(p ...

Storing a selected value in the database using Laravel Blade

Attempting to save information from a select field to the database. Tested this method: <div class="form-group"> <label>Type</label> <input style="width:10%" type="text" name="type" class="form-control" value="{{$findBook-& ...

What are some of the top languages, libraries, and modules used to create a web application for constructing templates?

Our company specializes in creating websites for membership-based associations. Currently, we utilize custom DLL's created with CodeGear Delphi to connect with a SQL Server database and implement a unique HTML template language. Essentially, our templ ...

Issues encountered with the functionality of the AngularJS greetController Controller

Currently exploring AngularJS, I am following a tutorial and have hit a roadblock trying to get the greetController controller to function properly. Below is the HTML code: <!DOCTYPE html> <html> <head> <title>HTML.it</titl ...

Enhance your projects with the power of React Bootstrap and React.PropTypes validation

I've set up a Rails 5 application with browserify and react-rails. While I can load components and install packages via npm, the browser console shows 'Warning: You are manually calling a React.PropTypes validation function for the....' when ...

Issue with retrieving duration XML data using Jquery

Could there be a specific explanation as to why the term duration might not function properly in JQuery? For instance, consider this XML snippet: <video description="description etc" duration="43306" id="1144537378001" name="Fashion" thumbnail="http:// ...

Exploring the power of ElasticSearch alongside Mysql

As I plan the development of my next app, I am faced with the decision between using NoSQL or a Relational Database. This app will be built using ReactJS and ExpressJS. The data structure includes relational elements like videos with tags and users who li ...

What do you think of the unique JSON syntax found in the React-Redux-Firebase documentation? Valid or not?

The React-Redux-Firebase documentation showcases a sample code snippet. import { compose } from 'redux' import { connect } from 'react-redux' import { firebaseConnect, populate } from 'react-redux-firebase' const populates = ...

Automatically fill in the Modal popup

Today, I encountered a challenge while trying to keep the current page in a jQuery data table. Clicking on the "Edit" link in a row would open a modal pop-up and fill in the controls. However, this action resulted in a postback that set the page back to pa ...