Recently I was working on a project that used a shortcode to output tabbed content on the page. For styling purposes, all groups of siblings (adjacent HTML elements with the same .sibling-element selector) that were produced by the shortcode needed to be wrapped in a common parent container.

But there was a slight problem: each shortcode generated just one sibling element rather than an entire block of sibling elements. Because of that it was impractical to attempt to use PHP to wrap a group of sibling elements. That meant that we had to use Javascript (jQuery) to do the job for us. This is what we were aiming for:

Shortcode html output

Fortunately with jQuery, the task wasn’t too difficult. Step 1 was to target the first element in each .sibling-element group. This was accomplished with:

$(':not(.sibling-element) + .sibling-element, * > .sibling-element:first-of-type');

Next we iterated over each of those elements and select all subsequent .sibling-element selectors in the group with:

$(this).nextUntil(':not(.sibling-element)').addBack();

Finally, we wrapped the sibling groups with the wrapAll() method.

Here it is all put together:

See the Pen jquery-wrap-sibling-groups by Tim Jensen (@timothyjensen) on CodePen.

Check out the Gist if you just want to see the code.

I generally prefer to use PHP to output HTML, but in cases such as this it makes more sense to use a little jQuery to get the job done.

Reader Interactions

Comments

  1. Hi Tim, I needed this today! Thanks for the insights and code. I like to be clean with the PHP wrapping but sometimes it’s just not practical due to the CMS.

    • I totally agree, Luke. My approach is always to do as much processing as possible in PHP, but sometimes you have to hack together something like this :). Glad you found it helpful!

  2. Thanks for the code, Tim!

    What if I only want to apply this to sibling-elements in groups of X amount or more? For example, I could specify the amount as 5, and groups of 4 or less would not get wrapped.

Leave a Reply

Your email address will not be published. Required fields are marked *