2

I'm using the Divi theme builder on my site. I've placed captions under each of my images in a text block. The captions are all in italics. Could anyone tell me if it's possible for me add some JavaScript that would automatically recognise the caption lines and apply a CSS class to them? It would be good if this could be automated as it would be very time consuming to manually add the CSS class to each caption.

This is the HTML I'm using:

<div class="dmpro_timeline_item_description">
  <p>
    <a style="color: inherit;" href="https://path-to-image.jpg">
      <img decoding="async" loading="lazy" src="https://path-to-image.jpg" width="300" height="237" alt="" class="wp-image-2179 alignnone size-medium" srcset="https://path-to-image.jpg 300w, https://path-to-image.jpg 1024w, https://path-to-image.jpg 768w, https://path-to-image.jpg 1536w, https://path-to-image.jpg 2048w, https://path-to-image.jpg 15w, https://path-to-image.jpg 1080w, https://path-to-image.jpg 1280w, https://path-to-image.jpg 980w, https://path-to-image.jpg 480w" sizes="(max-width: 300px) 100vw, 300px">
      <br>
      <em>This is the image caption text.</em>
    </a>
  </p>
  <p>This is where further details go (outside of the caption)</p>
</div>
Lloyd
  • 435
  • 3
  • 12
  • 29
  • Can you edit your question and include an HTML snippet (plus any JavaScript you have) so we can see what you've done? – ControlAltDel Jan 25 '23 at 16:14
  • if your caption can be identified, it's not complicated. Identified means: specific class, specific position in your html structure... but your html is needed to go further – pier farrugia Jan 25 '23 at 16:57
  • I'm so sorry, completely forgot to add my HTML in! I've just edited my question therefore. I don't have any JavaScript for this at the moment. I should add that the embedded images could be placed further down the text block too. So this would result in a structure like -> image, caption, descriptive text, another image, another caption, more descriptive text. – Lloyd Jan 25 '23 at 18:31

4 Answers4

1

If your images and captions will always be in the following format:

<img>
<br>
<em>Caption</em>

Then you can do it with CSS:

img + br + em {
  font-weight: bold; /* Or whichever styles you want to give to the captions */
}

If you want to actually add a class name to the <em> tags, you can do it with jQuery:

$('img + br + em').addClass('class-name-to-add');
kmoser
  • 8,780
  • 3
  • 24
  • 40
  • It would be better to descend from the parent div, don't you think? this seems very brittle. – Ringo Jan 29 '23 at 02:59
  • Thank you. How do I only target a specific page with your css? – Lloyd Jan 29 '23 at 15:20
  • @Lloyd Since you're using Divi, you can add a unique ID or class name (e.g. "foo") to a containing tag (e.g. the section). Then change my selector to, e.g. `div.foo img + br + em`. That will only select `` tags on the page containing `
    `.
    – kmoser Jan 29 '23 at 19:52
  • @kmoser why do you suggest using such a brittle selector? It's unusual – Ringo Jan 29 '23 at 20:25
  • Thank you Kmoser, your solution was exactly what I'm looking for. It may not be ideal (as @Ringo states) but it certainly does the job within our limited timescale! I don't have time to go through the hundreds of em's and manually apply a class name to them (as you suggested @Ringo) – Lloyd Jan 30 '23 at 00:09
  • @Ringo Because it's the simplest solution that gets the job done based on OP's requirements and specs. They are free to modify it to suit their needs, including optimizing it as they see fit. OP wrote _"I've placed captions under each of my images in a text block."_ but it's not clear whether "text block" means the `
    ` or the `

    `, so I just took the easiest route and selected based on proximity to the `` and `
    `, which I knew would always be there.

    – kmoser Jan 30 '23 at 03:26
0

Just add this to your javascript:

document.querySelectorAll('.dmpro_timeline_item_description em').forEach(item => {
    item.classList.add('new-class');
});
Ringo
  • 5,097
  • 3
  • 31
  • 46
  • Your solution seems a good one - thank you! Do I need to change ‘em’ to be ‘img + br + em’ so that it only targets those exact structures (instead of all italic texts)? – Lloyd Jan 29 '23 at 15:19
  • No, I would just keep it 'em'. If you have multiple 'em's inside the block, then try to add a classname to the 'em' you want to change, then change the selector to: `document.querySelectorAll('.dmpro_timeline_item_description em.new-em-class')` – Ringo Jan 29 '23 at 20:23
  • you should really take half an hour and read about basic CSS. there are so many basic tutorials online, and it would have helped you here. good luck – Ringo Jan 29 '23 at 20:27
0

you can use this

$(".dmpro_timeline_item_description")
.find('img[loading="lazy"]')
.next().next()
.addClass('some-class');

this will find images with lazy attribute and add class to second element after img.

0

Since CSS is read right to left you should always be as concise as possible, in this instance you should use the general sibling selector.

img ~ em {
    font-style: normal;
}

In JavaScript, to apply a class, do the following:

const captions = document.querySelectorAll('img ~ em')

for (caption of captions) {
 caption.classList.add('caption')
}

you could then style this as follows:

.caption {
    font-style: normal;
}

But at this point, I would say that it is better to handle this entirely in CSS.

Otherwise, you are asking the browser to find all the elements initially (to apply the class to them), and then further processing to style the elements based on the class that you have added. This could be done in one step by CSS.

Chris Warnes
  • 728
  • 1
  • 9
  • 18