How to Fix Tags Moving to Bottom when Hovered Due to Limited Space?

Recently, I've been facing an issue with the tags on my website. When I hover over them, a remove icon appears, causing the tags to increase in size. This results in a problem where, if I hover over the rightmost tag and there isn't enough space for the remove icon, the tag either jumps to the bottom or doesn't get hovered over at all. This inconsistent behavior is definitely impacting the user experience in a negative way.

Any suggestions on how I can fix this issue? Is there a way to prevent the tags from moving when there isn't enough space for the remove icon upon hovering? I'm thinking, could we implement a designated safe area on the right side of the design specifically for the remove icon, only visible when hovering over a tag? It's crucial for me to maintain the current layout.

.container {
  max-width: 500px;
    margin: 0 auto;
  display: flex; 
}
.tags-container { 
  background-color: #a3b3c6; 
  padding: 20px;
  display:flex;
  flex-wrap: wrap;
}
.tag {
  display: inline-flex;
  transistion: all 1s ease-in-out; 
  padding: 3px;
  background-color: white;
  border: 1px solid black;
}
.tag-close {
  margin-left: 10px; 
  height: 16px;
  width: 16px;
  display:none;
}
.tag:hover {
  background-color: red; 
}
.tag:hover .tag-close {
  display: block;
}

.tags-remove-all {
      display: flex;
    align-items: center;
    padding: 0 10px;
    font-size: 32px;
}
<div class="container">
<div class="tags-container">
  <div class="tag">
    LBL-12334455579
    <div class="tag-close">
      x
    </div>
    </div>
  <div class="tag">
    LBL-12334578
    <div class="tag-close">
      x
    </div>
    </div>
  <div class="tag">
    LBL-1233
    <div class="tag-close">
      x
    </div>
    </div>
  <div class="tag">
    LBL-12334
    <div class="tag-close">
      x
    </div>
    </div>
  <div class="tag">
    LBL-12334
    <div class="tag-close">
      x
    </div>
    </div>
  <div class="tag">
    LBL-12334
    <div class="tag-close">
      x
    </div>
    </div>
</div>
  <div class="tags-remove-all">
    x
  </div>
</div>

Answer №1

It appears to be a stylistic decision, you could extend the tags to include the cross without needing to hover over them.

If you prefer the cross to only show on hover, you could overlay it on the text within the tag when hovered, which wouldn't affect the tag's length as it's simply positioned over the text.

Here's a simple demonstration:

.container {
  max-width: 500px;
    margin: 0 auto;
  display: flex; 
}
.tags-container { 
  background-color: #a3b3c6; 
  padding: 20px;
  display:flex;
  flex-wrap: wrap;
}
.tag {
  display: inline-flex;
  transistion: all 1s ease-in-out; 
  padding: 3px;
  background-color: white;
  border: 1px solid black;
}
.tag-close {
  height: 16px;
  width: 16px;
  background-color: white;
  position: absolute;
  float: right;
  display:none;
}
.tag:hover {
  background-color: red; 
}
.tag:hover .tag-close {
  display: block;
}

.tags-remove-all {
      display: flex;
    align-items: center;
    padding: 0 10px;
    font-size: 32px;
}
<div class="container">
<div class="tags-container">
  <div class="tag">
    LBL-12334455579
    <div class="tag-close">
      x
    </div>
    </div>
  <div class="tag">
    LBL-12334578
    <div class="tag-close">
      x
    </div>
    </div>
  <div class="tag">
    LBL-1233
    <div class="tag-close">
      x
    </div>
    </div>
  <div class="tag">
    LBL-12334
    <div class="tag-close">
      x
    </div>
    </div>
  <div class="tag">
    LBL-12334
    <div class="tag-close">
      x
    </div>
    </div>
  <div class="tag">
    LBL-12334
    <div class="tag-close">
      x
    </div>
    </div>
</div>
  <div class="tags-remove-all">
    x
  </div>
</div>

Answer №2

In order to address this issue and prevent the tags from shifting to the bottom when hovered over, you can utilize the visibility property instead of display to hide and reveal the close button. By using the visibility property, the element will remain hidden but occupy its original space, thus avoiding any sudden movements.

.wrapper {
  max-width: 600px;
  margin: 0 auto;
  display: flex;
}

.tag-wrapper {
  background-color: #c4d6e0;
  padding: 15px;
  display: flex;
  flex-wrap: wrap;
}

.tag {
  display: inline-flex;
  transition: all 0.5s ease-in-out;
  padding: 3px;
  background-color: #ffffff;
  border: 1px solid #000000;
  position: relative;
}

.tag-close {
  position: absolute;
  top: 0;
  right: 0;
  height: 18px;
  width: 18px;
  visibility: hidden;
}

.tag:hover {
  background-color: #ff0000;
}

.tag:hover .tag-close {
  visibility: visible;
}

.remove-all {
  display: flex;
  align-items: center;
  padding: 0 8px;
  font-size: 28px;
}
<div class="wrapper">
<div class="tag-wrapper">
  <div class="tag">
    TAG-1234
    <div class="tag-close">
      x
    </div>
    </div>
  <div class="tag">
    TAG-5678
    <div class="tag-close">
      x
    </div>
    </div>
  <div class="tag">
    TAG-9101
    <div class="tag-close">
      x
    </div>
    </div>
  <div class="tag">
    TAG-1121
    <div class="tag-close">
      x
    </div>
    </div>
</div>
  <div class="remove-all">
    x
  </div>
</div>

Answer №3

To prevent flickering, I have applied a slight padding to the right of each tag.

In order to display the close button for the container without flickering on hover, I have set the opacity of the close button to 0. This ensures a smooth transition when hovering over the last tags in each row.

Since showing or hiding the close button upon hovering the last tag cannot be achieved with CSS alone, I have added a small script to handle this functionality. Thank you for your understanding.

document.addEventListener("DOMContentLoaded", function() {
  updateRightmostTags();
  showCloseButton();
});

window.addEventListener('resize', function() {
  updateRightmostTags();
});

function updateRightmostTags() {
  var tags = Array.from(document.querySelectorAll('.tags-container .tag'));
  tags.forEach(tag => tag.classList.remove('rightmost'));

  var currentTop = tags[0].getBoundingClientRect().top;
  tags.forEach((tag, i) => {
    if (tag.getBoundingClientRect().top !== currentTop) {
      tags[i - 1].classList.add('rightmost');
      currentTop = tag.getBoundingClientRect().top;
    }
  });

  tags[tags.length - 1].classList.add('rightmost');
}

function showCloseButton() {
  var tagElements = document.querySelectorAll('.tag');
  var closeButton = document.querySelector(".tags-remove-all");

  tagElements.forEach(tag => {
    tag.addEventListener('mouseenter', function(event) {
      if (event.target.classList.contains('rightmost')) {
        closeButton.style.opacity = "1";
      }
    });

    tag.addEventListener('mouseleave', function(event) {
      if (event.target.classList.contains('rightmost')) {
        closeButton.style.opacity = "0";
      }
    });
  });
}
.container {
  max-width: 600px;
  margin: 0 auto;
  display: flex;
}

.tags-container {
  max-width: 500px;
  background-color: #a3b3c6;
  padding: 20px;
  display: flex;
  flex-wrap: wrap;
}

.tag {
  display: inline-flex;
  position: relative;
  transition: all 1s ease-in-out;
  padding: 3px;
  padding-right: 20px; /* Added padding for flickering */
  background-color: white;
  border: 1px solid black;
}

.tag-close {
  position: absolute;
  right: 3px;
  top: 50%;
  transform: translateY(-50%);
  margin-left: 10px;
  height: 16px;
  width: 16px;
  visibility: hidden;
}

.tag:hover .tag-close {
  visibility: visible;
}

.tags-remove-all {
  display: flex;
  align-items: center;
  padding: 0 10px;
  font-size: 32px;
  opacity: 0;
}

.tags-container:after {
  content: '';
  width: 26px;
  display: inline-block;
  opacity: 0;
}

.tags-container:hover:after {
  opacity: 1;
}

.tags-container {
  background-color: #a3b3c6;
  padding: 20px;
  padding-right: 50px;
  display: flex;
  flex-wrap: wrap;
  flex-grow: 1;
}
<div class="container">
  <div class="tags-container">
    <div class="tag">
      LBL-12334455579
      <div class="tag-close">
        x
      </div>
    </div>
    <div class="tag">
      LBL-12334578
      <div class="tag-close">
        x
      </div>
    </div>
    <div class="tag">
      LBL-12334578
      <div class="tag-close">
        x
      </div>
    </div>
    <div class="tag">
      LBL-12334578
      <div class="tag-close">
        x
      </div>
    </div>
    <div class="tag">
      LBL-12334578
      <div class="tag-close">
        x
      </div>
    </div>
    <div class="tag">
      LBL-1233
      <div class="tag-close">
        x
      </div>
    </div>
    <div class="tag">
      LBL-12334
      <div class="tag-close">
        x
      </div>
    </div>
    <div class="tag">
      LBL-12334
      <div class="tag-close">
        x
      </div>
    </div>
    <div class="tag">
      LBL-12334
      <div class="tag-close">
        x
      </div>
    </div>
  </div>
  <div class="tags-remove-all">
    x
  </div>
</div>

Answer №4

You mentioned that the current design cannot be altered, but does that restriction only apply to the HTML? Here are some examples that maintain the original HTML structure while making changes solely to the CSS.

The initial example showcases padding the button on the left and right to center the text, allowing space for the remove icon. Upon hovering, the extra padding is removed to reveal the icon.

.tag {
  padding: 3px 16px;
}
.tag:hover {
  padding: 3px;
}

.container {
  max-width: 500px;
  margin: auto;
  display: flex; 
}
.tags-container { 
  background-color: #a3b3c6; 
  padding: 20px;
  display: flex;
  flex-wrap: wrap;
}
.tag {
... (Remaining code omitted for brevity)


In the second example, the remove icon is initially hidden and only appears upon hover. This setup maintains consistent button layout without shifting.

.tag-close {
  visibility: hidden;
}
.tag:hover .tag-close {
  visibility: visible;
}

.container {
  max-width: 500px;
  margin: auto;
  display: flex; 
}
.tags-container { 
... (Remaining code omitted for brevity)


Furthermore, this example introduces the use of flex-grow: 1 in the .tag rule.

.tag {
  flex-grow: 1;
}

.container {
  max-width: 500px;
  margin: auto;
  display: flex; 
}
.tags-container { 
... (Remaining code omitted for brevity)


To diversify, a Grid example is also included for demonstration purposes.

.tags-container { 
  display: grid;
  grid-template-columns: repeat(3, auto);
}

.container {
  max-width: 500px;
  margin: auto;
  display: flex; 
}
.tags-container { 
... (Remaining code omitted for brevity)

Answer №5

It seems to me that having x displayed on all elements by default is the most anticipated approach, considering other software practices.

On another note, the top response to this query might provide you with the solution you're seeking: Expanding div on hover in a flex row wrap container causes shifting of children elements

Answer №6

To create a negative margin-right effect on .tags-container, you can apply a margin of size .tag-close in CSS. However, in order to hide the displacement, wrap .tags-container in an additional element with overflow:hidden; style:

.container {
  max-width: 500px;
  margin: 0 auto;
  display: flex; 
}

/* wrapper */
.tags{
  overflow: hidden;
}

.tags-container { 
  background-color: #a3b3c6; 
  padding: 20px;
  display: flex;
  flex-wrap: wrap;
}

.tags-container:hover{
    margin-right: -16px; /* 👈 */
}

.tag {
  display: inline-flex;
  transition:background-color .2s; 
  padding: 3px;
  background-color: white;
  border: 1px solid black;
}

.tag-close {
  margin-left: 10px; 
  height: 16px;
  width: 16px;
  display:none;
}

.tag:hover {
  background-color: red; 
}

.tag:hover .tag-close {
  display: block;
}

.tags-remove-all {
  display: flex;
  align-items: center;
  padding: 0 10px;
  font-size: 32px;
}
<div class="container">
  <div class="tags">
    <div class="tags-container">
      <div class="tag">
        LBL-12334455579
        <div class="tag-close">x</div>
      </div>
      <div class="tag">
        LBL-12334578
        <div class="tag-close">x</div>
      </div>
      <div class="tag">
        LBL-1233
        <div class="tag-close">x</div>
      </div>
      <div class="tag">
        LBL-12334
        <div class="tag-close">x</div>
      </div>
      <div class="tag">
        LBL-12334
        <div class="tag-close">x</div>
      </div>
      <div class="tag">
        LBL-12334
        <div class="tag-close">x</div>
      </div>
    </div>
  </div>
  <div class="tags-remove-all">x</div>
</div>

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

Height of Owl Carousel on mobile devices

On my desktop, I have an image that covers the entire screen using Owl Carousel. However, when viewed on a phone device, the same image only takes up one-third of the screen size. How can I adjust the height so that it appears taller on a phone? I' ...

Next.js encounters an error: TypeError - dispatch function is missing

I've encountered a problem while implementing global authentication in my Next.js app, similar to how I would do it in React.js. The issue arises with a TypeError: dispatch is not a function error when attempting to call dispatch! I've tried var ...

Guide on retrieving the initial value from HTML and passing it to the controller in AngularJS during page load

<ul> <li ng-init="formData.mdpSunday='5'"> <input ng-model="formData.mdpSunday" name="mdpSunday" type="radio" value="5"> </li> </ul> app.controller(&a ...

Ember.js: Storing function prototypes as objects

My interface consists of four vertical panels: The first panel displays the menu for selecting data The second panel allows you to choose a filter from a list The third panel shows the results based on the selected filter The fourth panel displays detail ...

Attention: NextJS/React + Django Rest Framework encountered a non-boolean attribute `crossOrigin` with a value of `true`

I've been encountering this warning message but I'm unsure of its source or how to resolve it. It seemingly appeared out of nowhere as I revisited earlier commits where the warning was not present during my initial work on them. My suspicion is t ...

What could be the reason behind the open state being null?

Trying to utilize a prop value to update a state, but consistently receiving null. The prop value is confirmed to have a valid boolean value. Below is the constructor of the child component: constructor(props: any) { super(props); this.set ...

Is there a way to automatically scroll vertically to a specific line in HTML?

Trying to explain this is a bit tricky. I am looking to add an element to the HTML that prompts the browser to scroll vertically to its location automatically when loaded, similar to an anchor. So: | visible area | | content html | | content html | ...

A sleek Javascript gallery similar to fancybox

I'm currently working on creating my own custom image gallery, inspired by fancybox. To view the progress so far, please visit: I've encountered some issues with the fade effects of #gallery. Sometimes the background (#gallery) fades out before ...

Tips on utilizing innerHTML or innerText to add content to the Evernote editor, a rich text editor

A method authored by Jayant was employed in this particular post how-to-insert-text-into-the-textarea-at-the-current-cursor-position to perform an insertion into the Evernote editor. The Evernote editor being a rich text editor, altering from el.value to ...

Creating a simulated dropdown menu using only CSS

I was able to create a select menu using only CSS, following some code I found. However, I am now facing an issue with overlaying divs. Whenever I hover or click on the "select menu", all the divs below it move down. I've attempted to adjust the z-i ...

How can you customize the transition of a drawer in your app?

I have a unique setup where I have two drawers, one on the left and one on the bottom. My goal is to create an interactive effect when the left drawer opens - specifically by increasing the marginLeft and reducing the width of the bottom drawer using some ...

Using tokens to make consecutive API calls in JavaScript/Node.js

After generating the token, I need to make sequential calls to 5 different APIs. The first API used to generate the token is: POST https://idcs-xxxx.identity.c9dev2.oc9qadev.com/oauth2/v1/token Using the username and password, I will obtain the token from ...

In the event that the get request fails, go ahead and clear the

Currently facing an issue and seeking a solution: I have a game running that retrieves the state of the game periodically. However, if a user logs out, the game ends but continues to send put requests at the set interval. I am exploring options like setti ...

Text Description: "Important Information Hidden Beneath Persistent Bar"

I have a website with a sticky header (position: fixed), and despite adding extra padding to the body, the main content Header and part of the paragraph are still hidden behind the fixed header. This issue only occurs on the homepage and on screens smaller ...

Guide on how to choose a radio button in IONIC with the help of angularJS

<ion-list> <ion-radio ng-model="choice" ng-value="'A'" ng-click='usedGNG("yes")'>Yes</ion-radio> <ion-radio ng-model="choice" ng-value="'B'" ng-click='usedGNG("no")'>No</ion-radio> </ ...

What is the best approach to increase the height of a div element dynamically

I've encountered an issue with a div tag containing an image that may exceed the screen size. When this happens, I want to increase the height of the div tag and have a footer displayed below it. Currently, my styling for the div tag looks like this: ...

The Ajax Form disappears from the page

After racking my brain for a while, I've come to the conclusion that it's time to seek some assistance. I have work tomorrow and I don't want to spend all night on this. The issue lies in my form which is located inside a modal, here is my ...

The success variable of the Ajax running continuously in a loop is not being refreshed

Within this code snippet, a for loop is utilized to iterate through an array called netnos[] and update the variable 'nets' for each item. Ajax is then invoked to call a PHP script that generates a listing, which is successfully outputted to the ...

Arrange elements in a TD in a row side by side using HTML

I just added a slider next to an input and added an input box after the slider. The problem is they are underneath my first input. I want them all side by side in the TD tag. Please help. Let me know if you need more code: <td>$ <input name=" ...

There seems to be nothing in the request.body that was sent

I've encountered an issue with my code - whenever I use postman or cURL to send a post request, the body is empty. const express= require('express'); const app = express(); app.use(express.json()) app.post('/',(req,res)=>{ ...