I have already several days looking for a solution CSS or component for making an image resizable (height and width) and over the image, elements keeping the position over the same X and Y coordinates of the image.
A simple code what I tried:
.img-container {
position: relative;
width: 100%;
height: 100vh;
background-color: antiquewhite;
}
.aspect-ratio-img {
width: 100%;
height: 100%;
object-fit: contain;
}
.overlay {
position: absolute;
top: 30%;
left: 30%;
}
<div class="img-container">
<img src="img.jpg" class="aspect-ratio-img" alt="Your Image">
<div class="overlay">Element</div>
</img>
</div>
But this is wrong. In the example, the "element" text should have been kept over the same column and row of the grid. But as I show in the image it maintains the Top and Left relative to the browser edge and not based on the position of the image
What would like to have is something like next gif:
If I find the solution, I will post it here.
I did a component with a slot which all you place there will be resized. I'm not using JQuery, but I use the library vue3-resize, you can also implement it without this library due to the VUE3 observer feature This solution was based in the post https://css-tricks.com/scaled-proportional-blocks-with-css-and-javascript/#article-header-id-1 Thanks a lot
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import 'vue3-resize/dist/vue3-resize.css'
const bodyMapContainer = ref(null)
const scalableContainer = ref(null)
const scale = ref(0)
onMounted(() => {
doResize(bodyMapContainer.value.offsetWidth, bodyMapContainer.value.offsetHeight)
})
const handleResize = ({ width, height }) => {
doResize(width, height)
}
const doResize = (width: number, height: number) => {
const innerWidth = scalableContainer.value.offsetWidth
const innerHeight = scalableContainer.value.offsetHeight
scale.value = Math.min(width / innerWidth, height / innerHeight)
}
</script>
<template>
<div ref="bodyMapContainer" class="body-map-container">
<resize-observer @notify="handleResize" />
<div
ref="scalableContainer"
class="scalable-container"
:style="{ transform: 'translate(-50%, -50%) ' + 'scale(' + scale + ')' }"
>
<slot></slot>
</div>
</div>
</template>
<style>
.body-map-container {
position: relative;
width: 100%;
box-sizing: border-box;
margin: 0 auto;
left: 0%;
}
.scalable-container {
width: 1000px;
height: 750px;
padding: 5px;
text-align: center;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
transform-origin: center center;
}
</style>
Use:
<ViewBoxPanel>
... place here everything you want
<ViewBoxPanel>
``