skip to Main Content

example of real layout

I have been playing with a pure html-css gantt-styled chart. Still a lot to go.

But I can’t find the solution to trigger "hover" on the time-axis vertical divs, which are position absolute, and are below all the contents drawn by each row.

Hovering the rows works as expected and also on their child-bars, but obstructs overlapped elements to be triggered.

I quickly made this shortened example on fiddle
https://jsfiddle.net/diegoj2020/52snopkb/17/

My objective is to highlight the date where the mouse is pointing at.

I am trying to avoid javascript for layouting or styling.
I would like to find the pure-css method if any.

In the fiddle example, the expected behavior is to also highlight the vertical bars when the mouse sits on any row.

fiddle example

Any help would be very appreciated.

/*
The attempt her eis to highlight the row, the column, and the insight bar/object, all of 3 at the same time when the mouse is over.
*/
* {
  margin: 0;
  padding: 0;
}

xy-plot {
  position: absolute;
  width: 95%;
  border: 1px solid red;
  padding: 5px;
  margin: 10px;
}

cols {
  position: absolute;
  display: block;
  left: 100px;
  right: 10px;
  height: 100%;
}

rows {
  position: relative;
  display: block;
  margin-top: 30px;
}

day {
  box-sizing: border-box;
  display: inline-block;
  background-color: #2222;
  ;
  width: calc(100% / 365);
  height: 100%;
}

day:nth-child(even) {
  background-color: #5552;
}

task {
  display: block;
  position: relative;
}

taskbar {
  display: inline-block;
  position: absolute;
  left: 250px;
  width: 100px;
  background-color: red;
  height: 100%;
  border-radius: 8px;
}

task:hover {
  background-color: darkgray;
}

day:hover {
  background-color: darkgray;
}

taskbar:hover {
  background-color: black;
}
<xy-plot>
  <cols>
    <script>
      // populate columns time-axis
      document.write('<day></day>'.repeat(365));
    </script>
  </cols>
  <rows>
    <script>
      // populate rows and inside elements
      document.write('<task>A Task<taskbar></taskbar></task>'.repeat(10));
    </script>
  </rows>
</xy-plot>

2

Answers


  1. The heart of your question is the ability for a mouse hover to apply to all elements in the z-index at the pointer location.

    enter image description here

    CSS does not support this. By default, :hover is only triggered on the element in front, or with the highest z-index, at the current pointer location.

    screenshot showing desired scenario

    body {
      margin: 1em;
    }
    
    .d {
      display: inline-block;
      margin-right: 3em;
    }
    
    .d > * {
      width: 6em;
      aspect-ratio: 1;
      opacity: 0.7;
    }
    
    .d > :first-child {
      background: red;
    }
    
    .d > :last-child {
      background: green;
      margin-top: -3em;
      margin-left: 3em;
    }
    
    .d > :hover {
      outline: 5px solid black;
    }
    
    .d2 > :last-child {
      pointer-events: none;  
    }
    <div class="d">
      <div></div>
      <div></div>
    </div>

    The only control CSS supports is the ability to hide an element from all mouse interaction by styling it with pointer-events: none. This effectively makes the element invisible to the mouse pointer, so :hover will trigger on the next-highest element in the z-order. (Of course, this won’t be of any help in your scenario.)

    screenshot showing hover applying to next element when front element is styled with pointer-events: none

    body {
      margin: 1em;
    }
    
    .d {
      display: inline-block;
      margin-right: 3em;
    }
    
    .d > * {
      width: 6em;
      aspect-ratio: 1;
      opacity: 0.7;
    }
    
    .d > :first-child {
      background: red;
    }
    
    .d > :last-child {
      background: green;
      margin-top: -3em;
      margin-left: 3em;
      pointer-events: none;  
    }
    
    .d > :hover {
      outline: 5px solid black;
    }
    <div class="d">
      <div></div>
      <div></div>
    </div>

    To solve it you will need to use script, because the DOM provides the method document.elementsFromPoint(x, y) which returns all elements at the specified coordinates. Set up a mousemove event listener on the parent element which calls this method.

    const d = document.querySelector('.d')
    
    const applyStyle = (arr, e) => {
      if (arr.includes(e))
        e.classList.add('hover')
      else
        e.classList.remove('hover')
    }
    
    d.addEventListener('mousemove', evt => {
      const arr = document.elementsFromPoint(evt.clientX, evt.clientY)
      Array.from(d.children).forEach(c => {
        applyStyle(arr,c)
      })
    })
    
    d.addEventListener('mouseout', evt => {
      Array.from(d.children).forEach(c => {
        c.classList.remove('hover')
      })
    })
    body {
      margin: 1em;
    }
    
    .d {
      display: inline-block;
      margin-right: 3em;
    }
    
    .d > * {
      width: 6em;
      aspect-ratio: 1;
      opacity: 0.7;
    }
    
    .d > :first-child {
      background: red;
    }
    
    .d > :last-child {
      background: green;
      margin-top: -3em;
      margin-left: 3em;
    }
    
    .d > .hover {
      outline: 5px solid black;
    }
    <div id="x" class="d">
      <div id="y"></div>
      <div id="z"></div>
    </div>
    Login or Signup to reply.
  2. To trigger a :hover effect on multiple overlapped tags with markers on both the X-axis (rows) and Y-axis (columns), you can use CSS combined with HTML structure and, if necessary, a touch of JavaScript.


    HTML Structure

    Define a grid-like structure with rows and columns. Each cell can have overlapping elements, and you use classes or data attributes to identify them.

    <div class="grid">
      <div class="row" data-row="1">
        <div class="cell" data-column="1"></div>
        <div class="cell" data-column="2"></div>
        <div class="cell" data-column="3"></div>
      </div>
      <div class="row" data-row="2">
        <div class="cell" data-column="1"></div>
        <div class="cell" data-column="2"></div>
        <div class="cell" data-column="3"></div>
      </div>
      <div class="row" data-row="3">
        <div class="cell" data-column="1"></div>
        <div class="cell" data-column="2"></div>
        <div class="cell" data-column="3"></div>
      </div>
    </div>
    

    CSS Styling

    Use the :hover pseudo-class to apply styles to cells and their corresponding markers on hover.

    /* Base grid styles */
    .grid {
      display: grid;
      grid-template-columns: repeat(3, 100px);
      grid-gap: 5px;
    }
    
    .cell {
      width: 100px;
      height: 100px;
      background: lightgray;
      border: 1px solid #ccc;
      position: relative;
    }
    
    /* Row and column highlights */
    .row[data-row="1"]:hover .cell,
    .cell[data-column="1"]:hover {
      background: lightblue;
    }
    
    .cell:hover {
      background: orange;
    }
    

    Advanced Dynamic Marker Triggering with JavaScript

    For dynamic interaction when cells overlap or for advanced visual effects, JavaScript can help.

    document.querySelectorAll('.cell').forEach(cell => {
      cell.addEventListener('mouseover', function () {
        const row = cell.parentElement.dataset.row;
        const column = cell.dataset.column;
    
        // Highlight cells in the same row
        document.querySelectorAll(`.row[data-row="${row}"] .cell`).forEach(cell => {
          cell.classList.add('highlight');
        });
    
        // Highlight cells in the same column
        document.querySelectorAll(`.cell[data-column="${column}"]`).forEach(cell => {
          cell.classList.add('highlight');
        });
      });
    
      cell.addEventListener('mouseout', function () {
        document.querySelectorAll('.highlight').forEach(cell => {
          cell.classList.remove('highlight');
        });
      });
    });
    

    CSS with JavaScript

    Add a highlight class for the dynamic effects.

    .highlight {
      background: yellow;
    }
    

    Explanation:

    • CSS-only solution works well for simple layouts and interactions but has limitations when handling complex overlap.
    • JavaScript solution dynamically highlights rows and columns on hover for more flexibility.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search