Can't find the exact same question, so if this is a duplicate please redirect me. I am Working with Nuxt. I have an image component that can should be able to handle different images of varying widths. The image will changes based on mobile/desktop view, meaning the image can become wider/narrower based on the screen. Below and above it I have a title and a description something like this:
<div> //flexbox with flex-direction column and justify center
<h2 >{{insightsImage.title}}</h3>
<img :src='ifMobile ? mobileImage.url : image.url' />
<p>some tekst could be very long</p>
</div>
What I would like is the title and the
to have the same max width as the image at ALL times and that it is centered on the page. So if I have a very long description it cuts off and stays neatly stacked.
Something like this:
I have tried various methods, and have a solution that works, but I am wondering if there is a better, maybe more vue way?
Ideally I would do this with just css, but I haven't found any solution that works with variable image widths.
my current solution is this:
<div>
<h2 :style='`max-width: ${imageSize}`'>{{insightsImage.title}}</h3>
<img :src='ifMobile ? mobileImage.url : image.url' />
<p :style='`max-width: ${imageSize}`'/>some tekst</p>
</div>
export default defineComponent({
computed: {
imageSize(): string {
if (!process.browser) return '' // need this because Image object does not exist on server side
const image = new Image();
image.src = this.image.url;
return `${image.width > 0 ? image.width : 800}px` // need this 0 check because sometimes for some reason it initially returns 0 as width (might be because of SSR), and most images will be minimal 800px wide
}
Out of all the solutions I have found this feels the LEAST hacky, but still not perfect
Looked into using refs like this: Using $refs in a computed property
But official docs recommend not to (ab)use refs in computed props, AND since the ref is not updated the computed width does not change if the image src changes.
Any other suggestions?
Ok, so answering my own question if someone needs this. Still not 100% happy, because I'm still using inline styles (but maybe i'n just nitpicky). My original solution doesn't always work, because when routing to the page the image size is sometimes 0 (as mentioned in a comment). After some trying I finally found a combination of using vue Mounted/Updated with image.onload to keep track of the image width when resizing the screen. So I ended up with this:
<div>
<h2 :style='`max-width: ${imageSize}`'>{{insightsImage.title}}</h3>
<img :src='ifMobile ? mobileImage.url : image.url' />
<p :style='`max-width: ${imageSize}`'/>some tekst</p>
</div>
export default defineComponent({
data() {
return {
imageSize: ''
}
},
updated() {
this.updateImageSize()
},
mounted() {
this.updateImageSize()
},
methods: {
updateImageSize() {
const vm = this
const image = new Image()
image.src = this.image.url
image.onload = function() {
vm.imageSize = `${image.width}px`
}
}
}
}
})