Is there a way to display shortened text only when hovering without altering the height of the list box?

Here is my script for a vue component :

<template>
  ...
    <b-card-group deck v-for="row in formattedClubs">
        <b-card  v-for="club in row"
                img-src="http://placehold.it/130?text=No-image"
                img-alt="Img"
                img-top>
            <h4 class="card-title" 
                @mouseenter="club.truncate = false"
                @mouseleave="club.truncate = true">
                <template v-if="club.truncate">{{trucateText(club.description)}}</template>
                <template v-else>{{club.description}}</template>
            </h4>
            <p class="card-text">
                {{club.price}}
            </p>
            <p class="card-text">
                {{club.country}}
            </p>
            <div slot="footer">
                <b-btn variant="primary" block>Add</b-btn>
            </div>
        </b-card>
    </b-card-group>
  ...
</template>

<script>
export default {
  data: function () {
    return {
      clubs: [
          {id:1, description:'chelsea is the best club in the world and chelsea has a great player', price:1000, country:'england'},
          {id:2, description:'liverpool has salah', price:900, country:'england'},
          {id:3, description:'mu fans', price:800, country:'england'},
          {id:4, description:'city has a great coach. Thas is guardiola', price:700, country:'england'},
          {id:5, description:'arsenal player', price:600, country:'england'},
          {id:6, description:'tottenham in london', price:500, country:'england'},
          {id:7, description:'juventus stadium', price:400, country:'italy'},
          {id:8, description:'madrid sell ronaldo', price:300, country:'spain'},
          {id:9, description:'barcelona in the spain', price:200, country:'spain'},
          {id:10, description:'psg buys neymar at a fantastic price', price:100, country:'france'}
      ]
    }
  },
  computed: {
      formattedClubs() {
          return this.clubs.reduce((c, n, i) => {
              if (i % 4 === 0) c.push([]);
              c[c.length - 1].push(n);
              this.$set(n, 'truncate', true); 
              return c;
          }, []);
      }
  },
  methods: {
      trucateText (value) {
          const length = 30;
          return value.length <= length ? value : value.substring(0, length) + "...";
      }
  }
}
</script>

When this script runs, the view will look like this:

https://i.sstatic.net/yB1lu.png

On hovering over the description, the result would be like:

https://i.sstatic.net/EvRkU.png

This causes a change in the height of the list box.

How can I address this issue?

The desired view should be similar to this:

https://i.sstatic.net/ORski.png

Answer №1

It seems like you're utilizing bootstrap-vue. Awesome! With the v-b-tooltip directive, you can easily manage hover behavior without manual tracking for each item in your computed property formattedClubs:

this.$set(n, 'truncate', true); // This line can be removed.

To implement the directive only when truncation is necessary, update your template as follows:

<h4 class="card-title"
    v-if="club.description.length > 30"
    v-b-tooltip.hover.bottom
    :title="club.description">
  {{trucate(club.description)}}
</h4>
<h4 v-else>{{club.description}}</h4>

You now have the freedom to customize the styling by overriding Bootstrap's default styles:

.tooltip.show {
  opacity: 1;
} 

.tooltip-inner {
  background: #fff;
  color: #000;
  padding: .5em 1em;
  border: 1px solid #bbb;
  box-shadow: 0 3px 8px rgba(0, 0, 0, .15);
}

.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow, .tooltip.bs-tooltip-bottom .arrow {
    position: relative;
    background: #fff;
  top: 1px;
  width: 16px;
}

.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow::before, .tooltip.bs-tooltip-bottom .arrow::before, .tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow::after, .tooltip.bs-tooltip-bottom .arrow::after {
  bottom: 0;
    left: 50%;
    border: solid transparent;
    content: " ";
    height: 0;
    width: 0;
    position: absolute;
    pointer-events: none;
}

.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow::after, .tooltip.bs-tooltip-bottom .arrow::after {
  border-color: rgba(255, 255, 255, 0);
    border-bottom-color: #fff;
    border-width: 8px;
    margin-left: -8px;
}

.tooltip.bs-tooltip-auto[x-placement^=bottom] .arrow::before, .tooltip.bs-tooltip-bottom .arrow::before {
  border-color: rgba(187, 187, 187, 0);
    border-bottom-color: #bbb;
    border-width: 9px;
    margin-left: -9px;
}

If you'd like to see a fully functional example, check out this sample on CodePen.

Answer №2

One approach would be to enclose the shortened text within a tooltip module. By passing the complete text as a property to this module, you can achieve the desired functionality.

To display the tooltip on hover, you can utilize the @mouseover function and remove it using @mouseleave.

The tooltip itself can be styled with absolute positioning and a specified maximum width using max-width. While I won't go into detail here, this should serve as a good starting point for your implementation.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Serving Static Files in a Vue 2 Application Using Express

I'm encountering an issue with serving express static data in a vue 2 project (using the webpack-simple template) due to differences in production and development structures. During development: localhost/app In production: server/some-directory/app ...

Is there a way to automatically shorten a text when it goes beyond the boundaries of a div container?

How can I prevent a paragraph in one of two adjacent div containers from having a line break without changing the container's size? The surrounding div uses display: flex to position its children side by side. Currently, I've applied the followin ...

Compatibility issues with jQuery observed in Firefox and Internet Explorer 11

Check out the code here: jsfiddle demo HTML CODE: <div class="first"> <!-- Part one --> <div class="acord_col"> <div class="img_class" id="exist_site"></div> <div class="intro_text"> </div> </div&g ...

Encountering generator crashes when using Vue Cli remote presets

While attempting to develop a remote Vue CLI preset on GitHub, I encountered a syntax error that I cannot seem to resolve. You can find my preset repository here: https://github.com/christoph-schaeffer/vue-preset The command I entered is as follows: vue ...

Transfer or duplicate an SVG image from the bottom div to the top div

Is there a way to move a div from the chart_div to the movehere div? I've tried duplicating it below the current svg, but I'm having trouble targeting just the header row ('g' element) specifically. Here is the HTML: <script type= ...

Create an element that spans the entire width of the page

Having trouble adjusting the width of the .navbar? It seems to only grow to one side and setting it to 100% width doesn't expand it to fill the whole page. Can anyone provide some guidance or assistance? Here's the code: return ( <div cla ...

What is the best way to fix this problem within Vue.js?

I am currently exploring the possibilities of [email protected] version. I attempted to implement v-if, v-else-if..... but encountered issues. For instance: <div v-if="type === 'A'"> A </div> <div v-else-if="type === &apos ...

Is there a method for displaying a gif with an alpha channel for transparency effects?

Is it possible to make the black color in a realistic gif animation transparent using CSS? The snow is white and everything else is black, but I want to overlay it on my header image with the snow falling realistically. I've seen animations of falling ...

Click a button to adjust the height of an element

My webpage features a dashboard with tabs on the left and corresponding content on the right. To ensure proper alignment, I have utilized Bootstrap to create two columns - one for the tabs and one for the content. However, I am facing an issue where the bo ...

How to retrieve values from Vue custom renderer's variable

I have been experimenting with implementing a custom renderer for the Vue Word Cloud component within Laravel. You can find the component here: https://github.com/SeregPie/VueWordCloud Initially, I prepare my word array using PHP (which is functioning co ...

Swap out the string variable when it is modified

To generate a string inside the "code" variable that combines the selected image values, the final code should appear similar to: "test1/A=1a/B=1b" or "test2/A=1b/B=1a", etc. If the user modifies icon "A," it should replace the value in the code instead of ...

Arranging content within columns according to their column position

As I design a grid with three columns, each grid box contains a div with a maximum width of 280px. Sometimes the grid columns exceed this width. To achieve my desired layout, I aim to align the content in the grid boxes so that the left column aligns to th ...

Errors encountered: Navigation guard causing infinite redirection due to unhandled runtime issue

My Vue3 router is set up with the following routes: export const routes: Array<RouteRecordRaw> = [ { path: "/", name: "Browse Questions", component: HomeView, meta: { access: "canAdmin", }, ...

What is the best way to extract a number from a string in JavaScript?

There are instances in HTML files where a <p> tag displays the price of a product, such as ""1,200,000 Dollar"". When a user adds this product to their cart, I want the webpage to show the total price in the cart. In JavaScript, I aim to e ...

What is the process of running PHP in a .ctp file within the CakePHP framework?

I have recently started working with CakePHP and I have a question about how PHP code is executed in a file with the .ctp extension. Can you explain how PHP is processed within a .ctp file in CakePHP? Additionally, I'm also curious about executing PHP ...

Is it possible to modify the default port from 8080 to a different value within Vue?

Currently, I've been using Vue.js and Node.js to develop my app. By default, Vue runs on port 8080 while Node runs on port 3008. However, due to specific circumstances, I need to change the port for Vue from 8080 to something else like 8086 or 3005. ...

"960-css: Building a Unique Framework for Sty

Considering the 960 gs CSS framework for implementation on my website. Is there any notable company utilizing this framework for their websites? Appreciate any insights. ...

Is there a way to disregard the active region of a child element while the parent is active?

Currently, I am working on building a to-do list application using React. In the CSS styling, I have implemented an animation for when an li element is active, causing it to expand in height. The issue arises from the fact that I have also set up an onClic ...

Changing the color of placeholder text with CSS on Squarespace

I'm having a tough time figuring out how to adjust the color of the placeholder text in my form fields. Despite being able to change the background color of the form fields, I can't seem to alter the text color. The placeholder text doesn' ...

Steps for displaying a bootstrap modal in alignment with the triggering button's position

Recently diving into the world of bootstrap and AngularJs has been quite the learning experience for me. One challenge I encountered was trying to implement a bootstrap modal dialog box to show additional details within a table column. My goal was to hav ...