2

I have an <div> container with an <img> and an ::after pseudo-element. Like so:

<div class="container" data-caption="this caption should be as wide as the image and then wrap">
  <img>
</div>
.container {
  display: inline-block
}
.container::after {
  display:      block
  background:   #aabbaa
  content:      attr(data-caption)
  line-height:  40px
  padding:      0 1rem
}    

The container should get its width from the contained image while the ::after element should wrap its content accordingly, like this:

enter image description here

Instead the after element does not wrap - see this codepen.

enter image description here

Alexander Presber
  • 6,429
  • 2
  • 37
  • 66
  • 3
    Speaking to semantics, you probably shouldn't be using a pseudo-element for content like this. [`
    ` and `
    `](http://html5doctor.com/the-figure-figcaption-elements/) are the more appropriate choice.
    – Bailey Parker Jan 19 '18 at 22:52
  • @Bailey I second that. And an even more important argument is accessibility! – agrm Jan 19 '18 at 23:03
  • 1
    Possible duplicate of [How to make image caption width to match image width?](https://stackoverflow.com/questions/30686191/how-to-make-image-caption-width-to-match-image-width) – Bailey Parker Jan 19 '18 at 23:15
  • @BaileyParker understood, thanks. – Alexander Presber Jan 21 '18 at 15:27
  • @MrLister You are absolutely right, my trial and error got me confused. Removed that part of my question. – Alexander Presber Jan 23 '18 at 05:47
  • @BaileyParker: yes, the linked answer works for my setup (using an ::after pseudo-element) as well, see here: https://codepen.io/MoMolog/pen/OzKWJB Can / should I mark my question as a duplicate now? If so: how? – Alexander Presber Jan 26 '18 at 10:46

2 Answers2

1

Edited for dynamically inheriting from the image rather than the text use max-width: min-content:

.container
  display: inline-block
  border: 1px dashed red
  max-width: min-content
  &::after
    display:      block
    background:   #aabbaa
    content:      attr(data-caption)
    line-height:  40px
    padding:      0 1rem
    white-space:  wrap
T-Rez
  • 83
  • 8
  • 1
    Right, thanks. It's just that I want the image (and specifically its width) to be *variable* and *determine* the width of the whole thing. – Alexander Presber Jan 19 '18 at 22:50
  • I realized that as I was posting it that this is not the solution you were looking for and only achieved the result for the presented scenario. – T-Rez Jan 19 '18 at 22:55
  • 1
    I hadn't ever used min-content before but this seems like a really good use for it. :) – T-Rez Jan 19 '18 at 23:07
  • `min-content` is exactly what is needed to do this right. unfortunately it does not work for IE at all. – Alexander Presber Jan 21 '18 at 15:29
1

You can use some positioning hacks, with a relative parent and absolute pseudo element. See here: https://codepen.io/palash/pen/dJabRr

Also, white-space: wrap doesn't exist, it's white-space: normal that you are looking for, and it's is the default value. (nowrap does exist, though.)

.container
  position: relative
  ...
  &::after
    ...
    position:     absolute
    left:         0
    right:        0

Edit: If you don't want to use absolute positioning (so that border comes around the caption too), you can use flexbox to do it –

Updated pen: https://codepen.io/palash/pen/BYyXjq

.container
  display: flex
  flex-direction: column
  align-items: flex-start
  width: min-content
  ...
  &::after
    background:   #aabbaa
    content:      attr(data-caption)
    line-height:  40px
    padding:      0 1rem
Palash Karia
  • 670
  • 4
  • 10
  • Thanks, I removed the useless `white-space: wrap` rule. The problem with this approach imho is, that the caption is "outside" the container and does not demand it's own layout space. – Alexander Presber Jan 26 '18 at 10:50
  • If you are okay with using flexbox, there's a way to do that too. Updated the answer with the code – https://codepen.io/palash/pen/BYyXjq – Palash Karia Jan 31 '18 at 04:00