Chris
Chris

Reputation: 14218

vue set img height based on width with dynamic styling

I have an image that should have 50% height of its width.

<img :src="post.image" ref="image" :style="{ height: imageHeight + 'px' }" />

imageHeight() {
            let image = this.$refs.image
            if(!image) return 0
            let height = image.clientWidth * 0.5
            return height
        }

Unfortunately image is undefined during the evaluation of imageHeight and it does not get reevaluated when the width changes. Is there some way to make it work with a watcher or some other way?

Upvotes: 3

Views: 22076

Answers (3)

Pablo
Pablo

Reputation: 2156

I had to find a solution to something similar making a square div.

new Vue({
    el: "#app",
    data: {
        initialWidth: 100,
        matchedWidth: null
    },
    mounted() {
        this.matchWidth();
    },
    methods: {
        matchWidth() {
            this.matchedWidth = this.$refs.box.offsetWidth;
        }
    },
    computed: {
        igCardStyle() {
            return {
                width: `${this.initialWidth}%`,
                height: `${this.matchedWidth}px`
            };
        }
    }
});
.box-wrapper {
    width: 200px;
}

.box {
    background-color: red;
/*  border: 1px solid black; */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" ref="app">
    <div class="box-wrapper">
    <div class="box" :style="igCardStyle" ref="box">
    </div>
        </div>
<hr>
    <p>width: {{initialWidth}}% of .box-wrapper or {{matchedWidth}}px</p>
    <p>height: {{matchedWidth}}px</p>
</div>

In this cas you have to watch out for borders present in your $refs.box that could vary the result.

If you need the height to be the half of the width try: calc(${this.matchedWidth} * 0.5)px on the computed style property.

Hope it helps! BR

Upvotes: 1

Dazzle
Dazzle

Reputation: 3083

You could also do

<div :style={ height: myComputedHeight + '%' }></div>

data() {
  return {
     myCount: 10,
     myTotal: 100
  };
},

computed: {
    myComputedHeight() {
        return Math.round((this.myCount / this.myTotal) * 100);
    }
}

Upvotes: 1

Roy J
Roy J

Reputation: 43881

You can use the load event to set a variable. It looks like you're using a computed, but there's no data change for it to respond to.

new Vue({
  el: '#app',
  data: {
    url: 'http://via.placeholder.com/200x200',
    imageHeight: null
  },
  methods: {
    setheight(event) {
      let image = event.target;
      this.imageHeight = image.clientWidth * 0.5;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
  <img :src="url" @load="setheight" :style="{ height: imageHeight + 'px' }">
  <div>{{imageHeight}}</div>
</div>

Upvotes: 10

Related Questions