0

I'm trying to get a CSS selector for <img> elements on their own line but not an in-line <img>. So it should match (example 1):

<p><img src="..."></p>

but not (example 2):

<p>Lorem <img src="..."> ipsum</p>

I tried img:only-child -- because if the text is a text node surely this shouldn't match example 2. But it does.

Why? I want margins for in-line images (example 2) but no margins for images on their own line (example 1).

Is there any way to achieve this?

Fabian S.
  • 2,441
  • 2
  • 24
  • 34
Leon S.
  • 1
  • 1
  • Do you have control of the HTML? If so, why do the standalone images need to be inside a `

    `? Or you could just add a class for inline vs standalone.

    – DBS Nov 17 '21 at 10:12
  • @DBS Do I have control of the HTML? Not really. This is for a CMS where the images are inserted by an editor. I personally could remove the

    via the source view but most users couldn't.

    – Leon S. Nov 17 '21 at 10:30
  • It appears there is no CSS selector to distinguish whether one element contains text and another element so some workaround would be required. – Leon S. Nov 18 '21 at 10:42

3 Answers3

3

You can use word-spacing that will add margin only in your second situation

p {
  word-spacing:50px;
}
<p><img src="https://picsum.photos/id/237/100/100"></p>
<p>Lorem <img src="https://picsum.photos/id/237/100/100"> ipsum</p>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • 2
    This only really works when there's a maximum of 1 word on each side of the image, otherwise the word spacing makes a mess of your regular text. – DBS Nov 17 '21 at 10:16
  • @DBS *This only really works when there's a maximum of 1 word on each side of the image* --> and this is what the OP is showing in his question – Temani Afif Nov 17 '21 at 10:19
  • It is, but I think there's a good chance that was simply to keep the example short. – DBS Nov 17 '21 at 10:25
  • @DBS You are correct, this was a trivial example, perhaps too trivial! – Leon S. Nov 17 '21 at 10:33
  • @Temani Afif I am looking to set the img style not the p style, but thanks for the suggestion. – Leon S. Nov 17 '21 at 10:33
  • @DBS that's why people need to make accurate and real examples instead of *simple* one far from their real use cases – Temani Afif Nov 17 '21 at 10:36
  • @LeonS. yes too trivial. I am answering based on the question information (Sorry but I cannot read your mind ..) – Temani Afif Nov 17 '21 at 10:36
1

If you have several words at the start before the image then unfortunately the word-spacing option doesn't really do it for you.

What you can do is position the p element back a bit, position the first letter forward by the same amount and give the image a margin left and right of the same amount.

This will then give you this outcome: enter image description here

This may be sufficient for your use case - it's drawback is that the img has a right hand margin in the img-only case. This may or may not matter to you. In the sense this is all within a p element I suspect it'll be OK as any following content will be on a newline.

* {
  margin: 0;
  padding: 0;
}

p::first-letter {
  margin-left: 20px;
}

p {
  margin-left: -20px;
}

p img {
  margin: 0 20px;
}
<p><img src="https://picsum.photos/id/1015/100/100"></p>


<p>More than one word of text <img src="https://picsum.photos/id/1015/100/100">
  </ "> and some more text</p>
A Haworth
  • 30,908
  • 4
  • 11
  • 14
  • Thanks. It's actually the

    that had l/r margins, so

    text

    and

    text one text two

    was fine with margins, but for

    I wanted no margins on the

    . Apologies if that wasn't clear.

    – Leon S. Nov 18 '21 at 10:46
0

I think the CSS solutions are good. Especially @AHaworth because it also takes into account when there are more words in the text. Which is very probably the case. Therefore also thumbs up!

For the sake of completeness, I have added a Javascript solution here.

w = document.querySelectorAll('.wrapper')

w.forEach((el) => {  
  if (el.childNodes.length > 1) {
    el.childNodes.forEach((e) => {
      if( e.length === undefined) {
        e.classList.add('addMargin')
      }
    })
  }
})
.addMargin {
  margin-left:20px;
  margin-right:20px;
}
<p class="wrapper"><img src="https://picsum.photos/id/237/100/100"></p>
<p class="wrapper">Lorem <img src="https://picsum.photos/id/237/100/100"> ipsum bla</p>
<p class="wrapper">Lorem ipsum <img src="https://picsum.photos/id/237/100/100"> ipsum bla </p>
Maik Lowrey
  • 15,957
  • 6
  • 40
  • 79