Change child style on parent hover, with :after - html

I have a button with a link inside it, and an animated underline for said link. Code used from here, (example).
To make sure the underline was not huge and far below the text, I applied the animation to the text itself. The problem with this is the hover radius is to small, and I would like the entire button to be able to trigger the animation.
Here is my css and html:
.menuButtonText {
display: inline-block;
position: relative;
padding-bottom: 3px;
}
.menuButtonText:after {
content: '';
display: block;
margin: auto;
height: 2px;
width: 0;
background: transparent;
transition: width .5s ease, background-color .5s ease;
}
.menuButtonText:hover:after {
width: 100%;
background: #E0E0E0;
}
.menuButton {
width: 200px;
height: 100px;
margin: 20px;
background-color: red;
}
<div class="menuButton"><a class="menuButtonText">MenuButton</a>
</div>
<div class="menuButton"><a class="menuButtonText">MenuButton</a>
</div>
<div class="menuButton menuButtonSelected"><a class="menuButtonText">MenuButton</a>
</div>
The "menuButton" class is the parent and much larger than the space the text takes up, which is the trigger I wanted, I can't seem to get other solutions to work, and I'm assuming thats because of the ":after".

This what you're after?
http://jsfiddle.net/19mdzLdk/
I added this css:
.menuButton:hover .menuButtonText:after {
width: 100%;
background: #E0E0E0;
}
Now on div hover, the text underlines.

Related

CSS hover Slider - Unable to complete

I want to do the following hover slider:
The blue part should slide from left to right when hovered on the red part. It should slide from the right part of the red part and not showing (i.e. should be sliding behind the red part). Blue part should initially be hidden behind the red and should not show at all The blue part will be bigger than the red part so it had to be hidden with overflow or something else. There should be no opacity transitioning, however other transitioning is acceptable
This is what I have thus far:
HTML:
<div class="container">
<div class="static-content">
</div>
<div class="overlay">
OverLay Content - this will be some text
</div>
</div>
CSS:
.container {
position: relative;
width: 200px;
height: 100px;
.static-content {
display: block;
background-color: red;
width: 100%;
height: 100%;
}
.overlay {
position: absolute;
top: 0;
right: 0;
background-color: #008CBA;
height:100%;
width: max-content;
transition: .5s ease;
}
}
.container:hover .overlay {
transform: translateX(100%);
height: 100%;
}
Problem is blue part is infront of red part.
add this to .overlay element z-index: -1; to make it behind the red
div
and if the red div is smaller so it doesnt hide it all then u can but transparent colored div at the part that u want to hide since u dont want to do it with overflow
You can give your blue div style a z-index to take it under the red one like this :
.overlay {
position: absolute;
z-index: -1;
top: 0;
right: 0;
background-color: #008CBA;
height:100%;
width: max-content;
transition: .5s ease;
}

How to shift element upwards to it's variable height using css

Main question
I have two divs, one nested inside the other and i wish to shift inner div outside (upwards) of outer div and slide-in it on a hover.
Markup is looking like so:
<div class="body">
<div class="inner">Green is variable-height text which slides in on viewport hover</div>
Blue is a viewport (<body>, visible part of a page), which content should be compressed upon green slide-in
</div>
And (a little pseudo) css:
.body {
background: #aaf;
height: 300px;
width: 300px;
overflow: hidden;
}
.inner, .body:hover .inner {
-webkit-transition:all linear 0.2s;
transition:all linear 0.2s;
}
.inner {
background: #afa;
width: 300px;
margin-top:-some-magic-to-get-this-div-height;
}
.body:hover .inner {
margin-top: 0;
}
And a final result animation i'd like to get, without using fixed height of green div:
Also, this example (with a guessed and hard-coded height value of 2.5em) on jsfiddle to experiment with:
http://jsfiddle.net/n7vyLoh4/20/
Possible partial work-around (not satisfactory)
It is possible to partially implement what i want, using transitioning max-height instead of transitioning margin-top, the transition of max-height: 0; -> max-height: 100%; with overflow: hidden; set at all times
works, but has two draw-backs:
it doesn't slide in, it's more like drops the curtain
it doesn't stop transition at the end of green div, it transits till the end of outer blue div, which especially noticeable at reverse transition, when it first travels all the way from bottom of blue div to bottom of green div before any effect is visible. Also, this means that despite transition time set to 0.2s, it will spend only fraction of this time on transiting trough green div, because this 100% are 100% of parent div, not inner one (and my question could be answered if there is a way to calculate the 100% of inner div height).
Here is an illustration:
And fiddle for that:
http://jsfiddle.net/bsd7vnwu/1/
This is the pure css solution, which means it does not require any scripts, just a browser that support transitions:
.body {
background: #aaf;
height: 300px;
width: 300px;
overflow: hidden;
}
.inner {
-webkit-transition:all cubic-bezier(0,.81,.4,1) 0.5s;
transition:all cubic-bezier(0,.81,.4,1) 0.5s;
}
.inner {
background: #afa;
width: 300px;
position: absolute;
margin-top: -100%;
float: left;
}
.body:hover .inner {
position: relative;
margin-top: 0;
}
And Fiddle is here
I think this is the effect you want. CSS doesn't allow you to get the height of an element to use in calc() for positioning and margins, so a little JS is needed.
CSS:
.body {
background: #aaf;
height: 300px;
width: 300px;
overflow: hidden;
}
.inner, .body:hover .inner {
-webkit-transition:all linear 0.2s;
transition:all linear 0.2s;
}
.inner {
background: #afa;
width: 300px;
overflow: hidden;
}
.body:hover .inner {
margin-top : 0 !important;
}
JS:
Array.prototype.forEach.call(document.getElementsByClassName('inner'), function (item) {
item.style.marginTop = (item.clientHeight * -1) + 'px';
});
Demo:
http://jsfiddle.net/09tyLr9b/
I added transition to your fiddle to get what i think you are looking for
.inner {
background: #afa;
width: 300px;
overflow: hidden;
max-height: 0;
transition:0.5s ease-out;
}
.body:hover .inner {
max-height: 100%;
transition:0.5s ease-in;
}
JSFIDDLE
and by lowering the time for transition:ease-out you will get a more responsive slide up when you mouse out of the div
like this JSFIDDLE
Another CSS solution after 2.5 years, using flex layout:
.body {
background: #aaf;
height: 300px;
width: 300px;
overflow: hidden;
}
.inner {
display: flex;
align-items: flex-end;
-webkit-transition: all cubic-bezier(0, 1, 0, 1) 0.5s;
transition: all cubic-bezier(0, 1, 0, 1) 0.5s;
background: #afa;
max-height: 0;
overflow: hidden;
}
.body:hover .inner {
-webkit-transition: all ease-in-out 0.5s;
transition: all ease-in-out 0.5s;
max-height: 100%;
}
<div class="body">
<div class="inner">Green is variable-height text which slides in on viewport hover</div>
Blue is a viewport (<body>, visible part of a page), which content should be compressed
Also on JSFiddle.

Image getting clipped inside circle and re-positioning after scaling

I want to display images as circle on my webpage. For that, I have an image set as background wrapped inside a div container. Both the divs (outer and inner) have been given a border radius of 50% to achieve this. I also want the image to zoom in oh hover, for which I have applied transform:scale on the inner div.
The image is getting clipped a bit from left and right sides so it doesn't appear as a perfect circle. However, when the image gets scaled up on hover, the image forms a perfect circle. I have tried re-positioning it with background position, tried using a bigger image, increased/decreased size of both divs, but no method is working.
Further, when the image gets zoomed in on hover (using transform:scale), it gets re-positioned slightly after the transformation is complete. Strangely, if I remove the transition effect (transition duration and transition-timing-function), then this re-positioning doesn't happen.
Can anybody figure out why this is happening and what is the solution?
I am using bootstrap (I know it has a class img-circle which draws circle, but I wish to use my own code).
You can see the code running here: http://jsfiddle.net/dk49/h9KZr/
Observe the clipping of image on left and right sides of the circle and how it gets into correct shape on hovering over it. You can also see the jittering of image on zooming when hovering over it.
<div class="container-fluid page-content-wrapper">
<div class="col-xs-12 col-sm-4">
<div class="circle-container">
<h2 class="img-header">Men</h2>
<div class="inner-circle img-men"></div>
</div>
</div>
</div>
CSS:
.page-content-wrapper {
max-width: 980px;
margin-left: auto;
margin-right: auto;
background-color: #000;
}
.circle-container {
max-width: 325px;
max-height:325px;
border-radius: 50%;
overflow: hidden;
position: relative;
margin: 20px auto 0 auto;
z-index: 5; /* for fixing chrome bug */
}
.inner-circle {
width: 100%;
height: 100%;
padding-bottom: 100%;
border-radius: 50%;
overflow: hidden;
position: relative;
transition: transform 0.15s ease-in-out;
}
.inner-circle:hover, .inner-circle:active {
transform: scale(1.1);
}
.circle-container:hover .img-header, .circle-container:active .img-header{
bottom: 30%;
background-color: rgba(255,255,255,0.9);
}
.img-header {
color: #fff;
bottom: 10%;
position: absolute;
width: 100%;
color: #000;
background-color: rgba(255,255,255,0.7);
font-size: 25px;
font-weight: 500;
padding: 7px;
text-align: center;
height: 43px;
vertical-align: middle;
z-index: 1;
transition: bottom 0.15s ease-in-out, background-color 0.15s ease-in-out;
}
.img-header:hover ~ .inner-circle, .img-header:active ~ .inner-circle {
transform: scale(1.1);
}
.img-men {
background: url(http://s8.postimg.org/qohfig4md/men.png) center center no-repeat;
background-size: contain;
}

How to get two sibling elements to transition simultaneously?

I have two elements in a div, an image that fades in and some text that changes color, but I am unable to get them to transition at the same time. In other words, the mouse can only be over one or the other.
I tried to put the properties in the div that contains them, but that did not help.
JSFiddle example
HTML:
<div id="selectors">
<div id="omselector">
<a href="stills.html">
<img class="noglow" src="images/stills/oldcog.png" alt="Old Work!">
<img class="glow" src="images/stills/oldcogglow.png" alt="Old Work">
<p class="button">OLD WORK</p>
</a>
</div>
</div>
CSS:
.button
{
float: bottom;
width: 350px;
font-size: 20pt;
text-align: center;
font-weight: 900;
color: #FFFFFF;
left: 0;
top: 200px;
-webkit-transition: color 1s;
-moz-transition: color 1s;
-o-transition: color 1s;
transition: color 1s;
z-index: 6:
}
.button:hover
{
color: #0df400;
}
#omselector
{
position: absolute;
height: auto;
width: 300px;
top: 40%;
left: 25%;
z-index: 7;
}
.glow, .noglow
{
width: 250px;
height: 250px;
position: absolute;
left: 70px;
}
To simultaneously change the styling of both elements on a mouse event, you can take advantage of the parent element's mouse event and use #omselector and its :hover pseudo class in the selectors.
For example:
#omselector:hover .button {/*...*/}
#omselector:hover .glow, .noglow {/*...*/}
See JSFiddle demo based on your own.
Try this fiddle
One thing to note is that, try to position the images and the text inside the #omselector so they both receive the hover event. (Notice this wouldn't work of you hover over from the left side.

How to apply an opacity without affecting a child element with html/css?

I want to achieve this using html and css:
I have tried to set the opacity of the container to 0.3 and the box to 1, but it doesn't work: both divs have 0.3 opacity.
jsFiddle of my try here
The effect I am trying to achive is a popup box that comes on top of the page. It is highlighted by fading the content below (by lowering the opacity).
You can use opacity in combination with background color, like this:
#container {
border: solid gold 1px;
width: 400px;
height: 200px;
background:rgba(56,255,255,0.1);
}
#box {
border: solid silver 1px;
margin: 10px;
width: 300px;
height: 100px;
background:rgba(205,206,255,0.1);
}
<div id="container">
containter text
<div id="box">
box text
</div>
</div>
​Live demo
As far as I know you can't do it in a simple way. There a couple of options here:
Use absolute positioning to position box "inside" the container.
#container {
opacity: 0.3;
background-color: #777788;
position: absolute;
top: 100px;
left: 100px;
height: 150px;
width: 300px;
}
#box {
opacity: 1;
background-color: #ffffff;
position: absolute;
top: 110px;
left: 110px;
height: 130px;
width: 270px;
}
<div id="container"></div>
<div id="box">
<p>Something in here</p>
</div>
Use Javascript - almost the same as above, but position and size don't have to be hardcoded.
You can't apply an opacity property without affecting a child element!
"Opacity applies to the element as a whole, including its contents, even though the value is not inherited by child elements. Thus, the element and its children all have the same opacity relative to the element's background, even if they have different opacities relative to one another... If you do not want to apply opacity to child elements, use the background property instead." https://developer.mozilla.org/en-US/docs/Web/CSS/opacity
If you want the opacity to be applied only to the background, without affecting the child elements, use:
background-color: rgba(255, 255, 255, .3)
However, you can achieve the desired effect if you place them inside a div parent element and use CSS position property:
.parent {
border: solid green 3px;
position: relative;
width: 400px;
height: 200px;
}
.sibling-one {
border: solid red 3px;
position: absolute;
box-sizing: border-box;
width: 400px;
height: 200px;
opacity: .3;
}
.sibling-two {
border: solid blue 1px;
margin: 10px;
width: 200px;
height: 100px;
position: absolute;
transform: translateY(50%);
}
<div class="parent">
<div class="sibling-one">
<p>A sibling's one element</p>
</div>
<div class="sibling-two">
<p>A sibling's two element</p>
</div>
</div>
Try using rgba as a 'pre content' overlay to your image, its a good way to keep things responsive and for none of the other elements to be effected.
header #inner_header_post_thumb {
background-position: center;
background-size: cover;
position: relative;
background-image: url(https://images.pexels.com/photos/730480/pexels-photo-730480.jpeg?w=1260&h=750&auto=compress&cs=tinysrgb);
border-bottom: 4px solid #222;
}
header #inner_header_post_thumb .dark_overlay {
position: relative;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.75);
}
header #inner_header_post_thumb .dark_overlay .container .header-txt {
padding-top: 220px;
padding-bottom: 220px;
color: #ffffff;
text-align:center;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt h1 {
font-size: 40px;
color: #ffffff;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt h3 {
font-size: 24px;
color: #ffffff;
font-weight: 300;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt p {
font-size: 18px;
font-weight: 300;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt p strong {
font-weight: 700;
}
<header>
<div id="inner_header_post_thumb">
<div class="dark_overlay">
<div class="container">
<div class="row header-txt">
<div class="col-xs-12 col-sm-12">
<h1>Title On Dark A Underlay</h1>
<h3>Have a dark background image overlay without affecting other elements</h3>
<p>No longer any need to re-save backgrounds as .png ... <strong>Awesome</strong></p>
</div>
</div>
</div>
</div>
</div>
</header>
See a working codepen here
Using background-color: rgba(#777788, 0.3); instead of opacity could maybe fix the problem.
Apply this css rule
.alpha60 {
/* Fallback for web browsers that doesn't support RGBa */
background: rgb(0, 0, 0);
/* RGBa with 0.6 opacity */
background: rgba(0, 0, 0, 0.6);
/* For IE 5.5 - 7*/
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);
/* For IE 8*/
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";
}
In addition to this, you have to declare background: transparent for IE web browsers.
For more details visit the following link:
http://robertnyman.com/2010/01/11/css-background-transparency-without-affecting-child-elements-through-rgba-and-filters/
Any child of an element with opacity set will take on that opacity.
To achieve this style you could use rgba colours and filters for IE for the background, and opacity on the textual elements. So long as the second box isn't a child of one of the text elements, then it won't inherit the opacity.
Another workaround is to simply use an overlay background to create a similar effect.
I personally like a black overlay with about a 65% opacity, but for what you are trying to do you may want to use a white overlay at round 70%.
Create a small (100 x 100 or less) PNG in Photoshop or GIMP that has the color and opacity you want. Then just set that as the background of your light box.
If you create multiple PNGs at different opacities you can easily switch between them with JS or dynamically at load via backend scripting.
It's not technically what you are trying to do, but aesthetically it can give a very similar effect and UX wise accomplishes the same thing. It is also very easy to do, and widely supported across pretty much everything.
Opacity will always inherits by the child element regardless whatever the element in there, there is no workaround up to today have suggested, when the moving of the child element outside the transparency background is not an option like in a popup menu/dialog box creation, use of background with the rgba is the solution.
Here is a input box that i created that i can turn on or off with the class property invisible by javascript
<div id="blackout" class="invisible">
<div id="middlebox">
<p>Enter the field name: </p>
<input type="text" id="fieldvalue" />
<input type="button" value="OK" id="addfname" />
</div>
</div>
CSS
#blackout {
z-index: 9999;
background: rgba(200, 200, 200, 0.6);
height: 100%;
width: 100%;
display: block;
padding: 0px;
clear: both;
float: left;
position: absolute;
margin-top: -10px;
margin-right: 0px;
margin-bottom: 0px;
margin-left: -10px;
}
#blackout #middlebox {
border: thick solid #333;
margin: 0px;
height: 150px;
width: 300px;
background-color: #FFF;
top: 50%;
left: 50%;
position: absolute;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
padding: 10px 50px 0px 50px;
}
#middlebox p {
float: left;
width:100%;
clear:both;
}
#middlebox input {
clear:both;
margin-bottom:10px;
}
#middlebox input[type=text]{
width:100%;
}
#middlebox input[type=button]{
float:right;
width:30%;
}
.invisible{
visibility:hidden !important;
}
Use such elements that you can add :before or :after. My solution
<div class="container">
<div>
Inside of container element is not effected by opacity.
</div>
</div>
Css.
.container{
position: relative;
}
.container::before{
content: '';
height: 100%;
width: 100%;
position: absolute;
background-color: #000000;
opacity: .25
}
This might not be the most orthodox method but you can use a small semi-transparent background image for each div / container that repeats. It does seem that in this day and age you should be able to achieve this in pure (simple not hackish) css with no js but as the answers above show it isn't that straight forward...
Using a tiled image might seem dated but will work no worries across all browsers.
You can add a container's sibling absolutely positioned behind container, with the same size, and apply opacity to it.
And use no background on your container.
Now container's children have no opaque parent and the problem vanishes.