CSS/JS:将鼠标悬停在元素上突出显示另一个元素

问题描述:

我创建的网格可以具有n rows,并分为两个视图:leftChild和rightChild。 leftChild与rightChild具有相同的行数,但leftChild保持原位。与rightChild唯一的区别是它可以水平滚动。当我将鼠标悬停在leftChild或rightChild元素上时,我想添加某种悬停效果......这很容易,但我想要做的是在整行上添加悬停效果。因此,如果我将鼠标悬停在leftChild的第3行上,我想突出显示rightChild中的第3行。CSS/JS:将鼠标悬停在元素上突出显示另一个元素

现在,理想情况下,我喜欢一个完整的CSS解决方案,类似于this,但这是不可能的,因为我的行不会直接跟在对方后面。我试图想出解决这个问题的另一种方式,但对于直接的CSS似乎不可能。

输入JavaScript。我正在考虑下一步是将JavaScript与CSS结合起来。我可以将一个悬停效果添加到一行,然后使用JavaScript将悬停类添加到另一个子对象的相应行中。 jQuery非常简单,但我正在寻找一种原生的JavaScript方法。

我在考虑的主要方法是在每个行类元素上添加一个mouseentermouseleave。我不太喜欢这种方法,因为那时我在每个行元素上设置了2个事件监听器......这似乎有点低效。无论如何,当你输入时,你可以获得你所徘徊的行号,然后将悬停类添加到所有这些行号元素中。当你离开时,你只需找到所有悬停的元素,并相应地删除。相应的代码如下:

HTML

<body onload="loaded()"> 
    <div id="parent"> 
     <div id="leftChild"> 
      <div>left child</div> 
      <div class="row row1">some content</div> 
      <div class="row row2">other content</div> 
      <div class="row row3">more content</div> 
     </div> 
     <div id="rightChild"> 
      <div>right child</div> 
      <div class="row row1"> 
       <span class="col1">column 1 content</span> 
       <span class="col2">column 2 content</span> 
       <span class="col3">column 3 content</span> 
       <span class="col4">column 4 content</span> 
       <span class="col5">column 5 content some really long content to trigger scrolling just for the purpose of this example</span> 
      </div> 
      <div class="row row2"> 
       <span class="col1">column 1 content</span> 
       <span class="col2">column 2 content</span> 
       <span class="col3">column 3 content</span> 
       <span class="col4">column 4 content</span> 
       <span class="col5">column 5 content some really long content to trigger scrolling just for the purpose of this example</span> 
      </div> 
      <div class="row row3"> 
       <span class="col1">column 1 content</span> 
       <span class="col2">column 2 content</span> 
       <span class="col3">column 3 content</span> 
       <span class="col4">column 4 content</span> 
       <span class="col5">column 5 content some really long content to trigger scrolling just for the purpose of this example</span> 
      </div> 
     </div> 
    </div> 
</body> 

JS

function loaded() { 
    /*var parent = document.getElementById('parent'); 
    parent.onmouseenter = function(event) { 
     console.log(event.target); 
    }; 
    parent.onmouseleave = function(event) { 
     console.log(event.target); 
    };*/ 

    var rows = document.getElementsByClassName('row'); 
    for (var i = 0; i < rows.length; i++) { 
     rows[i].onmouseenter = function(event) { 
      var splits = event.target.className.split(" "); 
      var elems = document.getElementsByClassName(splits[splits.length - 1]); 
      for (var j = 0; j < elems.length; j++) { 
       elems[j].className += " hover"; 
      } 
     }; 

     rows[i].onmouseleave = function(event) { 
      var hovers = document.getElementsByClassName('hover'); 
      var len = hovers.length; 
      for (var j = 0; j < len; j++) { 
       hovers[0].className = hovers[0].className.replace(/\shover(\s|$)/, ''); 
      } 
     }; 
    } 
} 

CSS

.row:hover, .hover { 
    background-color: lightblue; 
} 

.row { 
    height: 50px; 
    padding: 5px; 
    white-space: nowrap; 
} 

.row > span { 
    display: inline-block; 
    border: 5px solid black; 
} 

#leftChild, #rightChild { 
    float: left; 
} 

#rightChild { 
    width: 300px; 
    overflow: auto; 
} 

#rightChild .row { 
    display: inline-block; 
} 

jsFiddleHere

所以我想知道一些事情。

  1. 这是可能的只是直的CSS?
  2. 如果不是,我怎样才能让我的方法更有效率?
  3. 拥有一个事件处理程序或多个事件处理程序会更高效吗?

我知道我在这里问很多,但我讨厌提出多个问题,尤其是如果我不得不重复自己。我会很感激任何帮助。谢谢!

+0

嗯..使用表? :/ –

+0

我宁愿不要,我实际上试图使用SlickGrid(使用divs/span)...这只是一个玩具问题。 – incutonez

基于this jsPerf,直JavaScript的方法,我有最快的,混合的方法紧随其后 - 第二,我的意思是非常接近原生的JS方法 - 并且(几乎完全)jQuery方法最后死去 - 它相对于其他方法来说非常慢两项。

所有这些都可以在this jsFiddle看到。

JS

// Native JS approach... fastest (according to my jsPerf http://jsperf.com/removeclass-vs-native-js-remove-class/2) 
function loaded() { 
    var rows = document.getElementsByClassName('row'); 
    for (var i = 0; i < rows.length; i++) { 
     rows[i].onmouseenter = function(event) { 
      var row = this.className.match(/row-[\d]+/); 
      var elems = document.getElementsByClassName(row[0]); 
      for (var j = 0; j < elems.length; j++) { 
       elems[j].className += " hover"; 
      } 
     }; 

     rows[i].onmouseleave = function(event) { 
      var hovers = document.getElementsByClassName('hover'); 
      var len = hovers.length; 
      for (var j = 0; j < len; j++) { 
       hovers[0].className = hovers[0].className.replace(/\shover(\s|$)/, ''); 
      } 
     }; 
    } 
} 

// jQuery approach (slowest) 
/*$(document).ready(function() { 
    $('.row').on('mouseenter', function(event) { 
     var row = this.className.match(/row-[\d]+/); 
     $('.' + row).addClass('hover'); 
    }); 

    $('.row').on('mouseleave', function(event) { 
     $('.hover').removeClass('hover'); 
    }); 
});*/ 

// Hybrid approach (basically as fast as native JS approach) 
/*$(document).ready(function() { 
    var rows = document.getElementsByClassName('row'); 
    for (var i = 0; i < rows.length; i++) { 
    rows[i].onmouseenter = function(event) { 
     var row = this.className.match(/row-[\d]+/); 
     $('.' + row[0]).addClass('hover'); 
    }; 

     rows[i].onmouseleave = function(event) { 
      $('.hover').removeClass('hover'); 
     }; 
    } 
});*/ 

  1. 通过具有此结构的css:no,在css级别4之前不可用。
  2. 使用this和检查className追加到它,而新规则
  3. moouse徘徊&鼠标离开?

我得到这样的:通过jQuery,但对于测试我删除了类.row,不停的编号为一

$("[class*='row']").hover(
    function() { 
     $('head').append('<style class="'+this.className+'" rel="stylesheet" > .'+this.className+' {background-color:lightblue;} </style>'); 
$(this).mouseleave(function() { $('style.'+this.className).remove();}); 
}); 

http://codepen.io/gcyrillus/pen/bhglr

+0

但是,这比我的原生JavaScript方法更高效吗?我认为答案是“不”。此外,它不会突出显示整行......它会跳过分隔栏。 – incutonez

+0

我确实在两者之间放了一个空白,以显示这两个不同的元素。我使用jQuery,因为您可以使用简单的CSS类似选择器。当然,如果你需要在你的网站上使用jQuery这个特性,那么如果访问者还没有在浏览器缓存中,那么对于访问者来说,它是30KO。 –

+0

没错,但jQuery增加了一些开销,所以我认为一个直接的JS解决方案还是更好的......基本上所有这些都是一旦我的网格相当大时加起来的。 – incutonez