Applying CSS rules based on input checkbox status - css

I'm currently developing a site that uses the :checked variable to apply rules to the CSS. I've got a checkbox input that when triggered, should accomplish two things. The first thing it should do is expand a div from a height of 0 to 200 when checked, and back to 0 when unchecked. I had no problems with triggering that first task. The second thing that should be accomplished upon checking the box, is a transform: rotate(45deg) of a div with a "+" in it that should rotate 45 degrees into an "x" (not an actual x, but a rotated +).
I've currently got my code setup to display the animation on :hover, but that's just for illustrative purposes, that wouldn't be in my final code. So hover over the "+ to see what I'm trying to accomplish with the :checked input.
If you're willing to take a look at my code, and tell me what I'm doing wrong, I'd be greatly appreciative! Let me know if you have any questions.
Note: Ideally I'm looking for a pure CSS solution without the need for JS. Let me know if this isn't possible.
Here's my code pen.

I wrote a similar solution the other day, here.
Basically, you are limited when using the :checked method. You are relying on the adjacent and general sibling combinators, +, ~. If the element isn't a general preceding sibling, it isn't going to work.
In this example, .expand was not a preceding sibling. Therefore the solution is to place the input element at the root of the document, and then use the selector input[name='panel']:checked ~ label .rotate to change the .rotate element. Note, that the general sibling combinator, ~ is now also being used as opposed to the adjacent sibling combinator, +.
No need for JS - UPDATED EXAMPLE
Modified HTML:
<input type="checkbox" name="panel" class="hidden" id="panel"/>
<label for="panel">
Click Me
<div class="rotate">+</div>
</label>
<div class="expand">
Content goes here.
</div>
Updated CSS:
input[name='panel']:checked ~ label .rotate {
transform: rotate(45deg);
-o-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
It's worth noting that I moved the transition properties to the .rotate element too.

jQuery Solution:
http://jsfiddle.net/SinisterSystems/PUwh6/2/
Use an ID so jQuery can map out what you're doing easily without searching for classes all over the place.
HTML:
<label for="panel">
Click Me
<div id="rotate">+</div>
</label>
CSS:
#rotate {
width: 12px;
float: right;
font-size: 18px;
margin-top: -6px;
text-align: center;
transition: all 1s ease;
-o-transition: all 1s ease;
-moz-transition: all 1s ease;
-webkit-transition: all 1s ease;
}
#rotate.spin {
transform: rotate(45deg);
-o-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
jQuery:
$('#panel').on('click',function() {
$('#rotate').toggleClass('spin');
});

Related

Wired Rotatation in Tailwind

The two blocks behave differently when applying tailwind's "rotate(**deg)" and vanilla css "transform: rotate(**deg)". Please just hover the blue blocks to reproduce.
https://play.tailwindcss.com/Rgf2GJ6mim
Since I sometimes use css in #layer utilities to write nested styles, so could someone please help me understand this? Big Thanks!!
Despite it looks like both examples do the same thing it's not quite true. Let's find out the difference. All classes in your example are same but the last one
hover:[transform:rotate(1020deg)] generates this
.hover\:\[transform\:rotate\(1020deg\)\]:hover {
transform: rotate(1020deg);
}
while hover:rotate-[1020deg] this
.hover\:rotate-\[1020deg\]:hover {
--tw-rotate: 1020deg;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
Or if you fill in Tailwind variables with its values it all comes to comparison between
.hover\:\[transform\:rotate\(1020deg\)\]:hover {
transform: rotate(1020deg);
}
// and
.hover\:rotate-\[1020deg\]:hover {
transform: translate(0, 0) rotate(1020deg) skewX(0) skewY(0) scaleX(1) scaleY(1);
}
We're forgot about one VERY important class - rotate-0. It actually sets the starting point of CSS transition
.rotate-0 {
--tw-rotate: 0deg;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
Just remove rotate-0 from both of your examples and now there is no difference in transition. So what is happening?
It all comes in CSS transition from state 1 to state 2. (Let's remove last
parts with skew and scale)
First example - from translate(0, 0) rotate(0deg) to rotate(1020deg)
Second - from translate(0, 0) rotate(0deg) to
translate(0, 0) rotate(1020deg)
MDN says
The transform functions are multiplied in order from left to right, meaning that composite transforms are effectively applied in order from right to left.
See example: red square just rotating. Yellow - rotates but returns back to default position even on hover we do NOT changing translate property. We're assuming it will left the same but this is not how CSS transition works. When there are multiple transform occurrence the last one will override previous. That's why translate is not applied anymore on hover - we're "erasing" it. In order to fix it we need to keep translate on hover (blue example)
.example {
width: 60px;
height: 60px;
margin: 40px;
transition: 1000ms;
}
.example-1 {
background-color: red;
transform: rotate(0);
}
.example-2 {
background-color: yellowgreen;
transform: translate(100px) rotate(0deg);
}
.example-3 {
background-color: blue;
transform: translate(100px) rotate(0);
}
.example-1:hover {
transform: rotate(45deg);
}
.example-2:hover {
transform: rotate(45deg);
}
.example-3:hover {
background-color: blue;
transform: translate(100px) rotate(45deg);
}
<div class="example example-1"></div>
<div class="example example-2"></div>
<div class="example example-3"></div>
And that's exactly what happening in your example - you are missing translate function in compiled CSS and changing the default state of transformed object (it is not transitioning anymore - it just places the new state). We need to keep the order of the chaining functions in transform property to ensure everything will work as expected
So, few ways to fix it in Tailwind keeping initial state (rotate-0 class), both requires to change hover:[transform:rotate(1020deg)] class
First - add missing translate function - change class into hover:[transform:translate(0,0)_rotate(1020deg)]
Second - not so obvious - change --tw-rotate variable value, basically convert class into hover:[--tw-rotate:1020deg]
And finally as I said - just remove initial state (rotate-0) but sometimes it is not an option
See examples
It's not the best explanation but I tried to point you in some direction where the difference comes from

Image hover CSS for revolution slider

I'm using revolution slider and I'm stuck with a problem. As an example I use the original demo from here: https://revolution.themepunch.com/wordpress-photography-slider.
On the tab 'portfolio' you see images that shrink in size with a transition and look a bit darker when you hover over them. This is what I want as well but I can't figure out how.
In revolution slider you can add classes, ID's and CSS to specific images so what I probably need is a CSS code that makes this possible. I've tried several codes I found online but none of them do the trick because they all come with an html part as well.
My guess was: the image is already there, I don't need the html part, only assign classes or id's to the images and then give each image the same kind of CSS code.
Am I on the right track with this? And can anyone help me with the code for it?
Many thanks in advance!
add a class, then do some css
for example:
<img class="slider-img">
.slider-img:hover {
{
let me know if you need help with the css.
EDIT:
try this.
wrap each of your images around 2 divs, slider-img and img-wrap:
<div class="slider-img">
<div class="img-wrap">
<img src="http://science-all.com/images/wallpapers/stock-image/stock-image-15.jpg">
</div>
</div>
then do some css:
.slider-img {
width: 200px;
cursor: pointer;
}
.slider-img img {
width: 100%;
}
.slider-img:hover .img-wrap {
background-color: black;
transform: scale(0.7);
-o-transform: scale(0.7);
-ms-transform: scale(0.7);
-moz-transform: scale(0.7);
-webkit-transform: scale(0.7);
transition: all .5s ease-in-out;
-o-transition: all .5s ease-in-out;
-ms-transition: all .5s ease-in-out;
-moz-transition: all .5s ease-in-out;
-webkit-transition: all .5s ease-in-out;
}
.slider-img:hover .img-wrap img{
opacity: 0.5;
}
basically what the css is doing is that when you hover over the main div (.slider-img), the div containing the image (.img-wrap) gets scaled down by 70% by the css -webkit-transform: scale(0.7);
it also gets a background color of black with an opacity of 80%. this gives the darkened image effect.
-webkit-transition: all .5s ease-in-out; gives a smooth transition effect.
if you are wondering why there are 5 different lines of css for the same thing, thats because each line targets specific browsers. -o- is opera, -moz- is firefox etc.
also, make sure to change the .slider-img width to match your needs.
check out the working example on js fiddle:
here

CSS3 transform on click using pure CSS

I'm trying to get an image (a plus symbol) to rotate 45 degrees to create a cross symbol. I have so far managed to achieve this using the code below but its working on hover, I wanted to have it rotate on click.
Is there a simple way of doing so using CSS?
My code is:
CSS
img {
display: block;
margin: 20px;
}
.crossRotate {
-webkit-transition-duration: 1s;
-moz-transition-duration: 1s;
-o-transition-duration: 1s;
transition-duration: 1s;
-webkit-transition-property: -webkit-transform;
-moz-transition-property: -moz-transform;
-o-transition-property: -o-transform;
transition-property: transform;
}
.crossRotate:hover {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
HTML
<body>
<img class="crossRotate" src="images/cross.png" alt="Cross Menu button" />
</body>
Here is the jsfiddle demo.
If you want a css only solution you can use active
.crossRotate:active {
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
}
But the transformation will not persist when the activity moves. For that you need javascript (jquery click and css is the cleanest IMO).
$( ".crossRotate" ).click(function() {
if ( $( this ).css( "transform" ) == 'none' ){
$(this).css("transform","rotate(45deg)");
} else {
$(this).css("transform","" );
}
});
Fiddle
Method #1: CSS :focus pseudo-class
As pure CSS solution, you could achieve sort of the effect by using a tabindex attribute for the image, and :focus pseudo-class as follows:
<img class="crossRotate" src="http://placehold.it/100" tabindex="1" />
.crossRotate {
outline: 0;
/* other styles... */
}
.crossRotate:focus {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
WORKING DEMO.
Note: Using this approach, the image gets rotated onclick (focused), to negate the rotation, you'll need to click somewhere out of the image (blured).
Method #2: Hidden input & :checked pseudo-class
This is one of my favorite methods. In this approach, there's a hidden checkbox input and a <label> element which wraps the image.
Once you click on the image, the hidden input is checked because of using for attribute for the label.
Hence by using the :checked pseudo-class and adjacent sibling selector +, we could get the image to be rotated:
<input type="checkbox" id="hacky-input">
<label for="hacky-input">
<img class="crossRotate" src="http://placehold.it/100">
</label>
#hacky-input {
display: none; /* Hide the input */
}
#hacky-input:checked + label img.crossRotate {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
WORKING DEMO #1.
WORKING DEMO #2 (Applying the rotate to the label gives a better experience).
Method #3: Toggling a class via JavaScript
If using JavaScript/jQuery is an option, you could toggle a .active class by .toggleClass() to trigger the rotation effect, as follows:
$('.crossRotate').on('click', function(){
$(this).toggleClass('active');
});
.crossRotate.active {
/* vendor-prefixes here... */
transform: rotate(45deg);
}
WORKING DEMO.
Voila!
div {
background-color: red;
color: white;
font-weight: bold;
width: 48px;
height: 48px;
transform: rotate(360deg);
transition: transform 0.5s;
}
div:active {
transform: rotate(0deg);
transition: 0s;
}
<div></div>
You can also affect differente DOM elements using :target pseudo class.
If an element is the destination of an anchor target it will get the :target pseudo element.
<style>
p { color:black; }
p:target { color:red; }
</style>
Click me
<p id="elem">And I will change</p>
Here is a fiddle : https://jsfiddle.net/k86b81jv/
As jeremyjjbrow said, :active pseudo won't persist. But there's a hack for doing it on pure css. You can wrap it on a <a> tag, and apply the :active on it, like this:
<a class="test">
<img class="crossRotate" src="images/cross.png" alt="Cross Menu button" />
</a>
And the css:
.test:active .crossRotate {
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
}
Try it out... It works (at least on Chrome)!
You can use WebkitTransform along with Transition (transition: all 2s;) to make the desired rotation with animation.
<style>
div.a {
width: 150px;
height: 80px;
background-color: yellow;
transition: all 2s;
}
</style>
<div class="a" id="box">Your Image Here</div>
<button onclick="rotate()">Rotate </button>
<script>
function rotate()
{
x= document.getElementById("box");
x.style.WebkitTransform = 'rotate(' + 20 +'deg)';
}
</script>
The advantage with this method is that you can do it programmatically. You can specify the angle using javascript (Although this is not required in your partcular case).
Refer this.
.c-btn:hover,.c-btn-active {
transform: rotate(45deg);
}
You can use JavaScript to do this, with onClick method.
This maybe helps CSS3 transition click event

CSS- and HTML-only tabs not responding properly

This one really has me confused. It's probably something simple that I've missed, but I sure can't find it...
I've created a fiddle to show you what I'm talking about.
You see originally this had 4 sections, these scrolled through fine with all of the links working correctly. The client has since added 1 more section, now for some reason when I add a further radio link, the whole control of the slide show goes to pot. See what I mean here.
All I've added is an extra link and content area. Does anyone know what I'm doing wrong? If you erase the below from the jsfiddle you'll see that it works correctly, but with the label for tab 5, it gives up. I'm at a loss... Any help greatly appreciated!
<input id="tab-5" type="radio" name="radio-set" class="tab-selector-5" /> <label for="tab-5" class="tab-label-5">POS</label>
<div class="content-5"> <h2>Fullfilment</h2> <p>Whatever your project involves Expressive Print are experienced in delivering it for you. From daily pick and pack requirements to contract packing and bulk despatches we have the ideal space to work in - clean, modern and secure premises with packing teams who are all fully CRB checked, robust stock control systems, comprehensive insurance cover and expertise. This ensures the right things are packed in the right order and sent the right people – simple but critical. Selecting a fulfilment partner who has strong systems with full accountability and customer service resource is vital to ensure your product’s success.</p> </div>
Demo your Jsfiddle
Now you just add one line css in your css file
.tabs input.tab-selector-1:checked ~ .content .content-1,
.tabs input.tab-selector-2:checked ~ .content .content-2,
.tabs input.tab-selector-3:checked ~ .content .content-3,
.tabs input.tab-selector-4:checked ~ .content .content-4,
.tabs input.tab-selector-5:checked ~ .content .content-5 // add this line in your css file
{
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-o-transform: translateY(0px);
-ms-transform: translateY(0px);
transform: translateY(0px);
z-index: 100;
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
filter: alpha(opacity=100);
opacity: 1;
-webkit-transition: all ease-out 0.3s 0.3s;
-moz-transition: all ease-out 0.3s 0.3s;
-o-transition: all ease-out 0.3s 0.3s;
-ms-transition: all ease-out 0.3s 0.3s;
transition: all ease-out 0.3s 0.3s;
}
Demo

CSS transition effect makes image blurry / moves image 1px, in Chrome?

I have some CSS that on hover, a CSS transition effect will moves a div.
The problem, as you can see in the example, is that the translate transition has the horrible side effect of making the image in the div move by 1px down/right (and possibly resize ever so slightly?) so that it appears out of place and out of focus...
The glitch seems to apply the whole time the hover effect is applied, and from a process of trial and error I can safely say only seems to occur when the translate transition moves the div (box shadow and opacity are also applied but make no difference to the error when removed).
The problem only seems to happen when the page has scrollbars. So the example with just one instance of the div is fine, but once more identical divs are added and the page therefore requires a scrollbar the problem strikes again...
2020 update
If you have issues with blurry images, be sure to check answers from below as well, especially the image-rendering CSS property.
For best practice accessibility and SEO wise you could replace the background image with an <img> tag using object-fit CSS property.
Original answer
Try this in your CSS:
.your-class-name {
/* ... */
-webkit-backface-visibility: hidden;
-webkit-transform: translateZ(0) scale(1, 1);
}
What this does is it makes the division to behave "more 2D".
Backface is drawn as a default to allow flipping things with rotate
and such. There's no need to that if you only move left, right, up, down, scale or rotate (counter-)clockwise.
Translate Z-axis to always have a zero value.
Chrome now handles backface-visibility and transform without the -webkit- prefix. I currently don't know how this affects other browsers rendering (FF, IE), so use the non-prefixed versions with caution.
You need to apply 3d transform to the element, so it will get its own composite layer.
For instance:
.element{
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
or
.element{
-webkit-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);
}
More about layer creation criteria you can read right here: Accelerated Rendering in Chrome
An explanation:
Examples (hover green box):
Problem: Transition may cause blink effect on sibling elements (OSx Lion, Chrome 30)
Solution: An element on its own composite layer
When you use any transition on your element it cause browser to recalculate styles, then re-layout your content even if transition property is visual (in my examples it is an opacity) and finaly paint an element:
The issue here is re-layout of the content that can make an effect of "dancing" or "blinking" elements on the page while transition happens.
If you will go to settings, check "Show composite layers" checkbox and then apply 3d transform to an element, you will see that it gets it's own layer which outlined with orange border.
After element gets its own layer, browser just needs to composite layers on transition without re-layout or even paint operations so problem have to be solved:
Had the same problem with embeded youtube iframe (Translations were used for centering iframe element). None of the solutions above worked until tried reset css filters and magic happened.
Structure:
<div class="translate">
<iframe/>
</div>
Style [before]
.translate {
transform: translateX(-50%);
-webkit-transform: translateX(-50%);
}
Style [after]
.translate {
transform: translateX(-50%);
-webkit-transform: translateX(-50%);
filter: blur(0);
-webkit-filter: blur(0);
}
I recommended an experimental new attribute CSS I tested on latest browser and it's good:
image-rendering: optimizeSpeed; /* */
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Chrome (and Safari) */
image-rendering: optimize-contrast; /* CSS3 Proposed */
-ms-interpolation-mode: nearest-neighbor; /* IE8+ */
With this the browser will know the algorithm for rendering
Just found another reason why an element goes blurry when being transformed. I was using transform: translate3d(-5.5px, -18px, 0); to re-position an element once it had been loaded in, however that element became blurry.
I tried all the suggestions above but it turned out that it was due to me using a decimal value for one of the translate values. Whole numbers don't cause the blur, and the further away I went from the whole number the worse the blur became.
i.e. 5.5px blurs the element the most, 5.1px the least.
Just thought I'd chuck this here in case it helps anybody.
I cheated problem using transition by steps, not smoothly
transition-timing-function: steps(10, end);
It is not a solving, it is a cheating and can not be applied everywhere.
I can't explain it, but it works for me. None of another answers helps me (OSX, Chrome 63, Non-Retina display).
https://jsfiddle.net/tuzae6a9/6/
Scaling to double and bringing down to half with zoom worked for me.
transform: scale(2);
zoom: 0.5;
Try filter: blur(0);
It worked for me
I've tried around 10 possibly solutions. Mixed them up and they still didn't work correctly. There was always 1px shake at the end.
I find solution by reducing transition time on filter.
This didn't work:
.elem {
filter: blur(0);
transition: filter 1.2s ease;
}
.elem:hover {
filter: blur(7px);
}
Solution:
.elem {
filter: blur(0);
transition: filter .7s ease;
}
.elem:hover {
filter: blur(7px);
}
Try this in fiddle:
.blur {
border: none;
outline: none;
width: 100px; height: 100px;
background: #f0f;
margin: 30px;
-webkit-filter: blur(10px);
transition: all .7s ease-out;
/* transition: all .2s ease-out; */
}
.blur:hover {
-webkit-filter: blur(0);
}
.blur2 {
border: none;
outline: none;
width: 100px; height: 100px;
background: tomato;
margin: 30px;
-webkit-filter: blur(10px);
transition: all .2s ease-out;
}
.blur2:hover {
-webkit-filter: blur(0);
}
<div class="blur"></div>
<div class="blur2"></div>
I hope this helps someone.
For me, now in 2018. The only thing that fixed my problem (a white glitchy-flicker line running through an image on hover) was applying this to my link element holding the image element that has transform: scale(1.05)
a {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transform: translateZ(0) scale(1.0, 1.0);
transform: translateZ(0) scale(1.0, 1.0);
-webkit-filter: blur(0);
filter: blur(0);
}
a > .imageElement {
transition: transform 3s ease-in-out;
}
None of this worked, what worked for me is scaling image down.
So depending on what size you want the image or what resoultion your image is, you can do something like this:
.ok {
transform: perspective(100px) rotateY(0deg) scale(0.5);
transition: transform 1s;
object-fit:contain;
}
.ok:hover{
transform: perspective(100px) rotateY(-10deg) scale(0.5);
}
/* Demo Preview Stuff */
.bad {
max-width: 320px;
object-fit:contain;
transform: perspective(100px) rotateY(0deg);
transition: transform 1s;
}
.bad:hover{
transform: perspective(100px) rotateY(-10deg);
}
div {
text-align: center;
position: relative;
display: flex;
}
h3{
position: absolute;
bottom: 30px;
left: 0;
right: 0;
}
.b {
display: flex;
}
<center>
<h2>Hover on images</h2>
<div class="b">
<div>
<img class="ok" src='https://www.howtogeek.com/wp-content/uploads/2018/10/preview-11.png'>
<h3>Sharp</h3>
</div>
<div>
<img class="bad" src='https://www.howtogeek.com/wp-content/uploads/2018/10/preview-11.png'>
<h3>Blurry</h3>
</div>
</div>
</center>
The image should be scaled down, make sure you have a big image resoultion
I had a similar problem with blurry text but only the succeeding div was affected. For some reason the next div after the one that I was doing the transform in was blurry.
I tried everything that is recommended in this thread but nothing worked.
For me rearranging my divs worked. I moved the div that blurres the following div to the end of parents div.
If someone know why just let me know.
#before
<header class="container">
<div class="transformed div">
<span class="transform wrapper">
<span class="transformed"></span>
<span class="transformed"></span>
</span>
</div>
<div class="affected div">
</div>
</header>
#after
<header class="container">
<div class="affected div">
</div>
<div class="transformed div">
<span class="transform wrapper">
<span class="transformed"></span>
<span class="transformed"></span>
</span>
</div>
</header>
filter: blur(0)
transition: filter .3s ease-out
transition-timing-function: steps(3, end) // add this string with steps equal duration
I was helped by setting the value of transition duration .3s equal transition timing steps .3s
The blurring occurred for me in Chrome only (Windows and Mac) when animating 'transform' in a keyframe animation. For me, the -webkit-optimize-contrast setting only partially helped. For best results I also had to use a "magic value" for scaleX (slightly larger than 1 instead of 1).
Here's the code that worked:
img {
image-rendering: -webkit-optimize-contrast;
}
#keyframes scale-in-left {
0% {
transform: scaleX(0);
opacity: 0;
}
100% {
transform: scaleX(1.000001);
opacity: 1;
}
}
Here's the code that didn't work (caused blurry images in Chrome):
#keyframes scale-in-left {
0% {
transform: scaleX(0);
opacity: 0;
}
100% {
transform: scaleX(1);
opacity: 1;
}
}
In the end, the "working" code removed most of the blurring, but not all of it. Safari and Firefox were still clearer without any special settings.
Note also that just resizing the browser window cleared up the unwanted blurring, suggesting perhaps that something is causing Chrome to fail to execute a final render pass (?).

Resources