Reduce bounds of expanded area for hover - html

Consider this contrived example. I have two divs, one of which grows to twice the size when you hover over it. When you move your mouse out of the edge of the expanded box, it returns to normal size.
Notably, it only returns to normal size once your mouse leaves the bounds of the expanded box. What I would like is for the box to go back to its normal size when your mouse leaves the bounds of the original size of the box.
I've been doing some reading of other questions and I think maybe pseudo elements are the way forward, but I can't figure it out. There are examples of maintaining the bounding box size when the element shrinks, but not when it expands.
.left {
width:300px; float:left;
}
.right {
width:300px; float:right; background-color: red;
}
.right:hover {
transform: scale(2);
}
<br>
</br>
<div style="width:800px">
<div class="left">foo</div>
<div class="right">bar</div>
</div>

Add pointer-events: none; to the div you want to transform. Apply the :hover effect to a parent div wrapping the transforming div. Example:
html, body {
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
.box {
height: 100px;
width: 100px;
background: tomato;
pointer-events: none;
}
.parentBox:hover .box {
transform: scale(2);
}
<div class="parentBox">
<div class="box"></div>
</div>
You can also make the box react to events by putting the event handlers on the box's parent, example on click:
html, body {
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
.box {
height: 100px;
width: 100px;
background: tomato;
pointer-events: none;
}
.parentBox:hover .box {
transform: scale(2);
}
<div class="parentBox" onclick="alert('You clicked the box!');">
<div class="box"></div>
</div>

Related

How to animate width on parent element with display:block/none on child elem

I have two children in one parent element where first child is always visible but second one is visible on hover only. Since I have fit-content set for parent's width when I hover the parent elem expands. What I need is a smooth transition for this expansion. I do all this in React. Thanks
Check context please:
.parent{
display: flex;
justify-content: space-evenly;
background-color: #f31d84;
width: fit-content;
}
.icon{
margin: 5px;
}
.text{
display: none;
margin: 5px;
}
.parent:hover .text{
display: block;
}
<div>
<div class='parent'>
<div class='icon'>
icon
</div>
<div class='text'>
texttexttexttext
</div>
</div>
</div>
I've managed to find a solution for my problem. The code:
<div>
<div class='parent'>
<div class='icon'>
icon
</div>
<div className='text-wrapper'>
<div class='text'>
texttexttexttext
</div>
</div>
</div>
</div>
.parent{
display: flex;
justify-content: space-evenly;
background-color: #f31d84;
width: fit-content;
}
.icon{
margin: 5px;
}
.text{
opacity: 0;
max-width: 0;
margin: 5px;
transition: 5s ease;
}
.text-wrapper{
width: auto;
}
.parent:hover .text{
opacity: 1;
max-width: 1000px;
}
You can't animate what is not a value. I mean that going from display: none to display: block can't be animate because they are not values.
It's a wrong implementation. Your parent element width in this example doesn't change on hover. If u want to animate things, a good practice is set width 0 to the child element and when parent element gets hovered div with the class text gets 50% of parent's width. you can achieve this through css only and react way. If u are interested let me know to edit this answer.
Transitioning from display: none to display: block will not work. Indeed, there is only a finite number of CSS properties that can be animated and display is not one (see: Animatable CSS properties on MDN).
The common way to do such a thing is to transition from width: 0 to width: 50% (or whatever value you want your block to be, just remember that auto will not work).
.parent {
display: flex;
justify-content: space-evenly;
background-color: #f31d84;
width: fit-content;
}
.icon {
margin: 5px;
}
.text {
display: block;
margin: 5px;
width: 0;
overflow: hidden;
transition: all .2s ease;
}
.parent:hover .text {
width: 50%;
transition: all .2s ease;
}
<div>
<div class='parent'>
<div class='icon'>
icon
</div>
<div class='text'>
texttexttexttext
</div>
</div>
</div>

position: fixed prevents elements to be centered properly

I want to center .donut-graphs inside .dashboard horizontally, so the space between the right edge of the sidebar and the left edge of .donut-graphs is the same as the space from the right edge of .donut-graphs and the right edge of the screen. I have managed to do so, but I had to remove position: fixed from .navbar. The problem is, I can't do that because my sidebar has to stay on top of the screen when you scroll up/down, and with position: fixed on .navbar, the graphs aren't centered properly.
HTML:
<div class="container">
<div class="navbar">
</div>
<div class="content">
<div class="dashboard">
<div class="donut-graphs">
<div class="dashboard-income">
Div 1
</div>
<div class="dashboard-overall">
Div 2
</div>
<div class="dashboard-spent">
Div 3
</div>
</div>
</div>
</div>
</div>
CSS:
body {
margin: 0;
}
.container {
display: flex;
align-items: stretch;
max-width: 100%;
min-height: 100vh;
}
.navbar {
background-color: #ddd;
flex: 0 0 230px;
position: fixed;
height: 100vh;
width: 230px;
}
.content {
flex: 1;
overflow-x: auto;
text-align: center;
}
.donut-graphs {
display: inline-flex;
border: 1px solid;
margin: 50px auto 0;
position: relative;
text-align: left;
}
.dashboard-income,
.dashboard-overall,
.dashboard-spent {
height: 256px;
width: 357px;
display: inline-block;
}
.dashboard-income {
background-color: green;
}
.dashboard-overall {
background-color: blue;
}
.dashboard-spent {
background-color: red;
}
How can I overcome the issue?
Demo
position: fixed puts element above everything. That element won't attach to any element in body because it is the way that works. It only becomes dependent of viewport
What you want to achive could be done with position: absolute but parent (whose child you want to center) has to be position: relative for this to work.
Read more about positioning elements in css here
.content { padding-left:230px; }
Should do the trick.
Assigning your navbar a fixed position takes it out of the document flow, so when centering your donut graphs the browser doesn't take the navbar into account.
Giving the .content element a padding equivalent to the width of the navbar makes up for this.
The only problem with this approach is that if .navbar changes dimensions, you'll need to change the padding on .content to match.

Element with border-radius shows artifacts after transition in Microsoft Edge

I have an element with border-radius applied that appears to leave a sort of trail (visual bug) behind when returning to its normal width after being shrunk to accommodate other enlarged elements. This seems to only happen when the border-radius property is used and the glitch level is proportional to the value of border-radius.
Basically, there are two elements inside a container with display: flex. The second element increases in width on hover and so the other element needs to shrink in order to not overflow. When I stop hovering, on the second element, the first one returns to its normal width, but it leaves a strange visual trail of its edge (pun unintended).
Before hover:
During hover:
After hover (the bug):
#container {
display: flex;
align-items: center;
width: 50%;
margin: 0 auto;
}
#reduce {
background: #eee;
width: 100%;
height: 50px;
border-radius: 30px;
}
#hoverexpand {
transition: all 0.5s ease;
width: 20%;
}
#hoverexpand:hover {
width: 50%;
}
<div id="container">
<div id="reduce">
</div>
<div id="hoverexpand">
<span>Hover this</span>
</div>
</div>
Again, this only happens on Microsoft Edge and I'm baffled as to what might be causing it. Is this a known bug? Is there any workaround?
There is a workaround. You can force Edge to repaint the affected element by promoting it to a composite layer with translateZ.
You only have to set the following rule to your #reduce element:
transform: translateZ(0);
Here is the working example:
#container {
display: flex;
align-items: center;
width: 50%;
margin: 0 auto;
}
#reduce {
flex: 2 0;
background: #eee;
height: 50px;
border-radius: 30px;
transform: translateZ(0);
}
#hoverexpand {
flex: 1 0;
transition: flex 0.5s ease;
}
#hoverexpand:hover {
flex: 2 0;
}
<div id="container">
<div id="reduce">
</div>
<div id="hoverexpand">
<span>Hover this</span>
</div>
</div>

Reposition div left of another div rather than below

I am attempting to tile a webpage with div elements of various sizes. However, I am running into an issue with once x number of div elements have filled the width of the screen the following div is placed below the previous 'row', rather than being floated to fit into space between elements in the previous 'row'. The code below better demonstrates what I mean; I'd like the 'game' div to be floated to fit into the space above where it is currently positioned.
h1 {
color: white;
}
.center {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
.container {
display: inline-block;
}
.default {
margin: 1em;
float: left;
}
/* For hover text */
.hover_img {
width: 100%;
height: 100%;
position: relative;
float: left;
}
.hover_img h4 {
color: white;
}
.hover_img:hover img {
opacity: .2;
}
.hover_img:hover .center_text {
display: block;
}
.center_text {
position: absolute;
top: 50%;
left: 0;
display: none;
font-weight: bold;
text-align: center;
}
img {
margin: 0;
}
.rectangle-tile-horizontal {
height: 15em;
width: 35em;
}
.red {
background-color: rgba(255, 63, 63, 0.8);
}
#game, #game img {
width: 30em;
height: 30em;
}
#app, #app img {
width: 40em;
height: 35em;
}
<div class="container">
<div class="rectangle-tile-horizontal red center default">
<h1><b>Projects</b></h1>
</div>
<div class="rectangle-tile-horizontal hover_img default" id="app">
<img src="http://cohenwoodworking.com/wp-content/uploads/2016/09/image-placeholder-500x500.jpg">
<div class="center_text"><h4>Web App</h4></div>
</div>
<div class="hover_img default" id="game">
<img src="http://cohenwoodworking.com/wp-content/uploads/2016/09/image-placeholder-500x500.jpg">
<div class="center_text"><h4>Breakout</h4> </div>
</div>
I'm afraid what you want to do is actually re-order your divs to create a space-filling layout. To the best of my knowledge, using only CSS for this is difficult, if not outright impossible.
I suggest you take a look at this SO post, or perhaps even the Bulma framework is what you want.
If, however, you move away from re-ordering the containers automagically and instead look towards a solution that elastically adapts the width of each container to fill the available space while maintaining its "order" (first, second, third), I am sure CSS will be a viable solution. If you require assistance, please use the search or ask anew.
Create a style for your div class or id like
.className
{display:inline;}
and use it in your each div
Hope this will help you
An example of this
http://jsfiddle.net/JDERf/

Why doesn't the wrapper wrap around the box?

I'm struggling with a problem which seems simple:
My code:
* {
font-family: tahoma;
}
body {
background: #333;
}
.wrapper {
padding: 10px;
background: white;
width: 100%;
}
.box {
margin-top: 40px;
width: 1100px;
height: 400px;
background: #aaa;
}
<div class="wrapper">
<div class="box">
box
</div>
</div>
The box contained in the wrapper has a fixed size, which might overflow the wrapper on small screens. Why doesn't the wrapper wrap around the box? How would I do that?
You can also check out the issue in this jsFiddle.
In order to make this work:
Remove width: 100% and add to the wrapper display: inline-block.
Doing so, will enable the wrapper to have as much width as needed to wrap around the box. Putting width: 100% restricts your wrapper to the width of the screen and in case of the box having a bigger with than that of the screen, it won't work.
If you do not want to have a horizontal scrollbar, especially on narrower screens use: box-sizing: border-box on the wrapper.
CSS:
.wrapper {
display: inline-block; /* Ensures that the box stays wrapped */
padding: 10px;
background: white;
box-sizing: border-box; /* Ensures that there won't be a horizontal scrollbar */
}
Here is a working version of your jsFiddle, with both the wrapping issue mended and the horizontal scrollbar abolished.
* {
font-family: tahoma;
}
body {
background: #333;
}
.wrapper {
box-sizing: border-box display: inline-block;
padding: 10px;
background: white;
}
.box {
position: relative;
margin-top: 40px;
height: 400px;
background: #aaa;
}
<div class="wrapper">
<div class="box">
box
</div>
</div>
For reference:
display: inline-block;
box-sizing: border-box;
Use display:inline-block on the wrapper to resize the container based on the content inside.
The div element by default has display:block; so you need to change its display.
You should remove width:100%; from .wrapper class, then you can make it display:inline-block; or display:table;
*{
font-family:tahoma;
}
body{
background:#333;
}
.wrapper
{
padding:10px;
background:white;
display:inline-block;
}
.box
{
margin-top:40px;
width:1100px;
height:400px;
background:#aaa;
}
<div class="wrapper">
<div class="box">
box
</div>
</div>
Your problem occurs, because HTML documents, by default, display all elements as display: block.
There are two ways to do it as our friends have mentioned before.
First one is to use inline-block value for the display property:
body{
display: inline-block;
}
The second way is to use max-width:
div.wrapper{
max-width: 100%;
/*we have set height property to auto to have coefficient between width & height*/
height: auto;
}
For more information visit these webpages:
inline-block
max-width
You can solve the problem by using the following css:
* {
font-family: tahoma;
}
body {
background: #333;
}
.wrapper {
padding: 10px;
background: white;
display: inline-block;
}
.box {
margin-top: 40px;
width: 1100px;
height: 400px;
background: #aaa;
}
<div class="wrapper">
<div class="box">
box
</div>
</div>
The only change is I have added display: inline-block to .wrapper element.
Why wrapper doesn't wrap around the child div
The problem is all html element has some default CSS styling which gets applied by the browser.
In this case div gets a default property of display: block; It is the same property that makes a default unstyled div to take up full available width of it's parent element.
As you can see with this: snapshot of chrome dev tools
*The css style highlighted in red rectangle is the default styling applied by the browser.
*The red underlined text tells us about the width of the element. The fading out signifies that value of that property is computed by the browser.
** While we are at it I want to point you to a different problem that you might have faced with the previous code and if the goal was to make the wrapper to wrap box at all times.
If the .box div would have width far less than that of the width of the browser then another problem may arise which I have shown in the code snippet bellow.
* {
font-family: tahoma;
}
body {
background: #333;
}
.wrapper {
padding: 10px;
background: white;
}
.box {
margin-top: 40px;
width: 100px;
height: 400px;
background: #aaa;
}
<div class="wrapper">
<div class="box">
box
</div>
</div>
As you can see the box tries to cling to a side of wrapper.
You can read more about display css property here: CSS display property || CSS-Tricks