In my trivial example below, I would like to have the solid blue div grow on mouse-over, but to preserve this state as long as the cursor is inside the orange box.
Once the cursor leaves the orange box, the solid blue box should collapse. The orange box represents a row in a list.
The real implementation is in a tool-tip-like slide-out on a complex row full of other details.
.row {
border: 1px solid orange;
display: block;
height: 20%;
padding: 20px;
width: 400px;
}
.row div {
border: 1px dashed blue;
display: inline-block;
text-align: center;
padding: 20px;
width: 100px;
}
.row .right {
background: blue;
padding: 20px 0;
transition: width 0.5s ease;
width: 10px;
}
.row .right:hover {
width: 100px;
}
<div class="row">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
Of course, this can easily be accomplished with JavaScript (which is how it is currently implemented):
let right = $('.right');
right.mouseenter(() => right.addClass('hover'))
$('.row').mouseleave(() => right.removeClass('hover'))
.row {
border: 1px solid orange;
display: block;
height: 20%;
padding: 20px;
width: 400px;
}
.row div {
border: 1px dashed blue;
display: inline-block;
text-align: center;
padding: 20px;
width: 100px;
}
.row .right {
background: blue;
padding: 20px 0;
transition: width 0.5s ease;
width: 10px;
}
.row .right.hover {
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
But I would like, if possible, to use a purely CSS approach for reasons of code readability, performance and maintainability.
If it is in fact impossible, I will accept that as an answer.
The current implementation is in an Angular4 template, so we need to pepper the templates with directives like (mouseleave)="tooltipElement && hideTooltip($event.target.children)
which seem like they should be unnecessary to me.
Here is an approach that uses a little hack to simulate the preserve hover state thing. It does not keep it forever but for the duration you define as animation-delay. Probably 10 minutes of hovering is like forever in most scenarios, if you want to make it last longer you would just have to increase the number in the code below.
.row {
border: 1px solid orange;
display: block;
height: 20%;
padding: 20px;
width: 400px;
}
.row div {
border: 1px dashed blue;
display: inline-block;
text-align: center;
padding: 20px;
width: 100px;
}
.row .right {
background: blue;
padding: 20px 0;
transition: width 0.5s ease 600s;
width: 10px; /* Unfortunately, this has to be 'different' from ... */
}
.row .right:hover {
width: 100px;
transition: 0.5s;
}
.row:not(:hover) .right {
width: 10.01px; /* ... this width. See http://stackoverflow.com/q/43393653 */
transition: 0.5s ease;
}
<div class="row">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
With pure CSS you can't do exactly what you are describing. You can make the blue border grows when you hover the row but not when you hover the blue element and preserve while is hovering on the row.
So you can hover the row and apply to the right element, and if it fits with your requirements will be as this:
.row {
border: 1px solid orange;
display: block;
height: 20%;
padding: 20px;
width: 400px;
}
.row div {
border: 1px dashed blue;
display: inline-block;
text-align: center;
padding: 20px;
width: 100px;
}
.row .right {
background: blue;
padding: 20px 0;
transition: width 0.5s ease;
width: 10px;
}
.row:hover .right{
width: 100px;
}
<div class="row">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
I just wanted to in-line the single-listener solution proposed by @Shaggy in a comment above, for those cases when having event listeners might actually be fine.
{
let current=0;
document.getElementById("group").addEventListener("mouseover",event=>{
let target=event.target;
if(target.classList.contains("right"))
(current=target).classList.add("hover");
else if(target===event.currentTarget&¤t){
current.classList.remove("hover");
current=0;
}
},0)
}
body{
margin:0;
padding:20px;
}
#group{
border:1px solid #999;
display:inline-block;
padding:20px 20px 0;
}
.row{
border:1px solid #f90;
display:block;
height:20%;
margin:0 0 20px;
padding:20px;
width:400px;
}
.row>div{
border:1px dashed #00f;
display:inline-block;
padding:20px;
width:100px;
}
.row>.right{
background:#00f;
padding:20px 0;
transition:width .5s ease;
width:10px;
}
.row>.right.hover{
width:100px;
}
<div id="group">
<div class="row">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
<div class="row">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
<div class="row">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
</div>