Why the image gets pixelated when using the transform property - html

I want to make a rotating animation for the search icon, that when the input gets focused, then the icon rotates 90 degrees around the Y-axis, and then the text cursor appears, so it's like the search icon being transformed into the text cursor (try it with the code snippet below), but when I apply the transform property to the icon which is a png image, it gets pixelated and it doesn't look good, Is there a way to fix this problem?
Here's the difference:
.Navbar {
display: flex;
padding: 50px;
align-items: center;
justify-content: center;
}
.Navbar .SearchBox {
position: relative;
}
.Navbar .SearchBox input {
background-color: darkgray;
border-style: none;
color: transparent;
padding: 0px 16.5px 0px 10px;
font-family: 'vazir';
border-radius: 6px;
height: 35px;
outline: none;
width: 300px;
direction: rtl;
}
.Navbar .SearchBox img {
height: 17px;
position: absolute;
top: 9px;
right: 8px;
transform: rotateY(0deg);
transition: transform .3s ease-out;
}
.Navbar .SearchBox input:focus {
color: white;
transition: color 0s ease .3s;
}
.Navbar .SearchBox input:focus + img {
transform: rotateY(90deg);
transition: transform .3s ease-out;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<header class="Navbar">
<div class="SearchBox">
<input type="text">
<img src="https://i.ibb.co/DRLFR0w/search.png" alt="search">
</div>
</header>
</body>
</html>

This happens because when you define a transformation on the element it will create a new stacking context which will make the element have its own path in the renderer. Chrome apparently applies a different antialiasing algorithm for such elements in their own stacking context.
To workaround that, you can simply omit that rule and let the transition start from initial:
body{ background: #333 }
img { height: 17px; }
.transform {
transition: transform .3s ease-out;
}
:hover>.transform {
transform: rotateY(90deg);
}
<span><img src="https://i.ibb.co/DRLFR0w/search.png" alt="search"></span>
<span>
<img class="transform" src="https://i.ibb.co/DRLFR0w/search.png" alt="search"></span>

Related

Make a text scroll automatically, with CSS animation, only if it overflows

I want to have a div, that when you hover it, text scroll if it's larger than the div.
But for now the text will always scroll event if it's shorter.
Here is my html code :
https://codesandbox.io/s/gracious-glade-7z31zc?file=/index.html
In this exemple, I would like the animation disabled on the second as it fits in the container.
Do you know a way to do it in CSS ? Or do I have to use JS ?
Thanks.
Dont know it is possible in CSS, but its quite simple is JS.
First of all i made another class for hovering effect:
.scrolled:hover {
animation: scroll-rtl 15s linear forwards;
}
Then quick js as commented.
document.querySelectorAll('.chip-value') // get all elements you want
.forEach( item => { // iterate over them and get every as "item"
if(item.offsetWidth > 400){ // check if it's widthter than parent
item.classList.add('scrolled') // if is, add him class to scroll
}
})
.chip-container {
margin-left: 3px;
margin-right: 3px;
margin-top: 3px;
margin-bottom: 3px;
max-width: 400px;
height: 32px;
font-size: 0.8125rem;
display: inline-flex;
align-items: center;
/* WebkitBoxAlign: center; */
border-radius: 16px;
white-space: nowrap;
/* // outline: 0, */
text-decoration: none;
/* // border: 0, */
vertical-align: middle;
/* // boxSizing: 'border-box', */
overflow: hidden;
background-color: gray;
color: white;
}
.chip-value {
display: inline-block;
position: relative;
text-overflow: clip;
margin-right: 5px;
margin-left: 5px;
}
.scrolled:hover {
animation: scroll-rtl 15s linear forwards;
}
#keyframes scroll-rtl {
0% {
transform: translate(0);
}
100% {
transform: translate(-100%);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet/css" href="index.css" />
<title>Static Template</title>
</head>
<body>
<div class="chip-container">
<div class="chip-value">
Very very very very very very very very very very very very very very
very very very very very very very very very long
</div>
</div>
<div class="chip-container">
<div class="chip-value">
Not long
</div>
</div>
</body>
</html>
You wouldn't be able to do this with CSS alone, but you could use JS to check the size of the content inside of the container to compare it to the width of the container. If content > container, then scroll; else do nothing. Here's what I might do in this situation:
document.addEventListener('DOMContentLoaded', function(){
var elements = document.getElementsByClassName('chip-container');
for(var element of elements){
var pw = element.querySelector('.chip-value').offsetWidth;
var cw = element.offsetWidth;
if(pw > cw){
element.classList.add('animate-me-baby');
}
}
});
.chip-container {
margin-left: 3px;
margin-right: 3px;
margin-top: 3px;
margin-bottom: 3px;
max-width: 400px;
height: 32px;
font-size: 0.8125rem;
display: inline-flex;
align-items: center;
/* WebkitBoxAlign: center; */
border-radius: 16px;
white-space: nowrap;
/* // outline: 0, */
text-decoration: none;
/* // border: 0, */
vertical-align: middle;
/* // boxSizing: 'border-box', */
overflow: hidden;
background-color: gray;
color: white;
}
.chip-value {
display: inline-block;
position: relative;
text-overflow: clip;
margin-right: 5px;
margin-left: 5px;
}
.animate-me-baby:hover .chip-value {
animation: scroll-rtl 15s linear forwards;
}
#keyframes scroll-rtl {
0% {
transform: translate(0);
}
100% {
transform: translate(-100%);
}
}
<div class="chip-container">
<div class="chip-value">
Very very very very very very very very very very very very very very
very very very very very very very very very long
</div>
</div>
<div class="chip-container">
<div class="chip-value">
Not long
</div>
</div>

Why isn't transition for my input forms working?

I have tried to add transitions to my input forms but it doesn't work. I've read a lot of stack overflow posts but they haven't worked for me. A person said that it's because input has display: none but even after changing it, it still didn't work. I tried to be more specific when using transition but that didn't work. So I'm not sure how to fix this issue. The transition applies to the button but not to the input forms.
https://codepen.io/i-am-programming/pen/gOmydqv
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
href="https://fonts.googleapis.com/css2?family=Montserrat:wght#200&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="styles.css" />
<title>Document</title>
</head>
<body>
<nav>
Home
About
Store
Contact Us
</nav>
<div class="container">
<h1 class="login">Log In</h1>
<input type="text" placeholder="Username" class="username info" />
<input type="password" placeholder="Password" class="pass info" />
<input type="button" class="button" value="Submit" />
</div>
<script src="app.js"></script>
</body>
</html>
* {
margin: 0;
padding: 0;
font-size: 25px;
font-family: "Montserrat", sans-serif;
}
body {
background: url("images/background.jpeg");
background-size: cover;
}
a {
text-decoration: none;
margin-right: 30px;
color: #fff;
background-color: rgba(0, 0, 0, 0.7);
padding: 8px;
transition: 0.3s ease;
}
nav {
margin-top: 20px;
display: flex;
flex-direction: row;
justify-content: flex-end;
}
a:hover {
color: black;
background-color: rgba(255, 255, 255, 0.7);
}
.container {
display: flex;
flex-direction: column;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 500px;
height: 450px;
background-color: rgba(0, 0, 0, 0.7);
align-items: center;
}
.login {
color: white;
margin-top: 50px;
font-size: 45px;
}
input {
outline: none;
padding: 5px;
transition: 0.3s;
}
input:hover {
width: 400px;
}
.username {
position: absolute;
top: 45%;
left: 50%;
transform: translate(-50%, -50%);
}
.pass {
position: absolute;
top: 65%;
left: 50%;
transform: translate(-50%, -50%);
}
.button {
width: 150px;
margin-top: 250px;
}
Firstly your code in text and link are different. Secondly you can't use transition on display cause it's not animatable. You cna use opacity and visibility instead of display. If we come to our question..
You want to get bigger input place when user get hover it right? So in your example your input does not has any width and when you hover it you want to get a transition. For this you need to add a width value to your input so it will know where the change began and what you want at the end. Meanwhile the time you passed is your time attribute on your transition. So
input {
height: 30px;
width: 300px;
outline: none;
transition: 0.3s;
}
input:hover {
width: 400px;
}
It will know that when user hover on it, it will grow to 400px from 300px in 0.3s. That's it. Hope you get it.
I think you are missing transition property in the input, it will be like this:
input {
height: 30px;
width: 300px;
outline: none;
transition: all 0.5s ease;
}
input:hover {
width: 500px;
}
Read more of the CSS transition
It's because you didn't specify the width of your input

show child after parent hover transition

I have a problem here. I need the "sidebar-buttons" to appear after increasing the parent element's size by the hover.
gif w/ my problem
buttons have display none and after I hovering my sidebar-list-item their display change to flex, so I need this change appear after changing sidebar-list-item height and background.
here is my code:
html:
<div class="sidebar-list-item">
<div class="sidebar-main-items">
<div>Стретч-плёнки</div>
<img
src="./assets/icons/sidebar/paper-icon.svg"
width="32"
alt="paper icon"
/>
</div>
<div class="sidebar-buttons">
<button class="sidebar-button-buy" onclick="#">Купить</button>
<button class="sidebar-button-how" onclick="#">Как выбрать?</button>
</div>
</div>
css:
.sidebar-list-item {
font-weight: 500;
font-size: 14px;
min-height: 75px;
height: 100%;
display: flex;
align-items: center;
color: black;
border-bottom: 1px solid #f9f9f9;
transition: all 0.5s ease-in-out;
}
.sidebar-list-item:hover {
display: block;
min-height: 114px;
background-color: #ffca3a;
}
.sidebar-list-item:hover .sidebar-buttons {
display: flex;
}
.sidebar-list-item:hover .sidebar-main-items img {
opacity: 1;
}
What you need is animate the height of it.
First, set the heigth of content as auto.
Second, in buttons container, set max-height:0 and overflow:hidden.
Third, animate the buttons container to max-height:200px.
What happens?
The css will animation will take 400ms to reach 500px even if the container is smaller, so consider testing smaller values so the button animation doesn't finish before the main container animation.
Edit: Updated the snippet, added the transition-delay property on button animation to run 500ms after container animation.
.sidebar-list-item {
font-weight: 500;
font-size: 14px;
height: 50px;
display: block;
align-items: center;
color: black;
border-bottom: 1px solid #f9f9f9;
transition: all 0.5s ease-in-out;
padding:10px 0;
transition-delay: 500ms;
}
.sidebar-list-item:hover {
transition-delay: 00ms;
background-color: #ffca3a;
height:60px;
}
.sidebar-list-item:hover .sidebar-main-items img {
opacity: 1;
}
.sidebar-list-item:hover .sidebar-buttons {
max-height:150px;
transition: all 0.5s ease-in-out;
transition-delay: 500ms;
}
.sidebar-buttons{
transition: all 0.5s ease-in-out;
display: flex;
max-height:0;
overflow:hidden;
}
<div class="sidebar-list-item">
<div class="sidebar-main-items">
<div>Стретч-плёнки</div>
<img
src="./assets/icons/sidebar/paper-icon.svg"
width="32"
height="32"
alt="paper icon"
/>
</div>
<div class="sidebar-buttons">
<button class="sidebar-button-buy" onclick="#">Купить</button>
<button class="sidebar-button-how" onclick="#">Как выбрать?</button>
</div>
</div>

How to stop placeholder from transitioning back ? (CSS)

I was trying to create an input field with a transition effect to the placeholder, for that I used a <span> tag to hold the placeholder and transitioned it using the :focus CSS selector
It works pretty well but the problem is after we input the text and click anywhere outside the input area/text field area, the placeholder transitions back and overlaps with the text inputted.
I want the placeholder to not transition back if the text area currently has text in it.
Also, there is one more issue that the text field doesn't get selected if the placeholder is clicked.
How can I clear these bugs?
I've provided the code below:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Input</title>
<style>
body {
margin: 0px;
}
#top-heading {
padding: 1rem;
text-align: center;
margin: auto;
margin-bottom: 1rem;
}
textarea {
width: 85%;
display: block;
height: 10vh;
margin: 1.5rem;
margin-top: 0rem;
padding: 0.5rem;
font-size: large;
}
span {
position: absolute;
top: 6rem;
padding-left: 2.7rem;
color: rgb(121, 120, 120);
font-size: larger;
}
textarea:focus~span {
color: black;
font-size: 1.091rem;
transition: .6s ease;
transform: translate3d(-1.15rem, -1.9rem, 2rem);
}
</style>
</head>
<body>
<h1 id="top-heading">Input</h1>
<textarea id="txt-input"></textarea>
<span>Enter the input</span>
</body>
</html>
Can you please check the below code? Hope it will work for you. You need to give transition: .6s ease; property to span tag instead of textarea:focus~span.
Please refer to this link: https://jsfiddle.net/yudizsolutions/kjfc0z37/
<!DOCTYPE html>
<html lang="en">
<head>
<title>Input</title>
<style>
body {
margin: 0px;
}
#top-heading {
padding: 1rem;
text-align: center;
margin: auto;
margin-bottom: 1rem;
}
textarea {
width: 85%;
display: block;
height: 10vh;
margin: 1.5rem;
margin-top: 0rem;
padding: 0.5rem;
font-size: large;
}
span {
position: absolute;
top: 6rem;
padding-left: 2.7rem;
color: rgb(121, 120, 120);
font-size: larger;
transition: .6s ease;
}
textarea:focus~span {
color: black;
font-size: 1.091rem;
transform: translate3d(-1.15rem, -1.9rem, 2rem);
}
</style>
</head>
<body>
<h1 id="top-heading">Input</h1>
<textarea id="txt-input"></textarea>
<span>Enter the input</span>
</body>
</html>

Want to replicate youtube's autoplay toggle button in pure css

Until recently youtube used a tag named "paper-toggle-button". My script used that but since youtube removed it I've had to settle with a normal boring checkbox.
I don't just want an answer. I want to learn how it works. It bugs me that this advanced css doesn't click for me yet.
I've been trying to replicate it via tutorials that show in various ways how to make a sliding toggle button. But I'm not satisfied with the look. I want it to look as close to the youtube's toggle button as possible. At least one thing I've learned. The code below doesn't need any pictures which is good.
This requires advanced knowledge of css which I don't have.
Here's an example and it looks ugly. Because it must for instance manually put the label in the correct place. See .labelterm. I gave up when I couldn't use this tutorial code to add a checkmark.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1">
<title>Awesome checkbox</title>
<style type="text/css">
.mylabel {
position: relative;
display: block;
width: 60px;
height: 30px;
margin-bottom: 15px;
}
.mylabel input {
display: none;
}
.slidinggroove {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #ababab;
/*background: rgba(0, 0, 0, 0.1);*/
border-radius: 20px;
transition: all 0.3s ease;
}
.slidinggroove:after {
position: absolute;
content: "";
width: 28px;
height: 28px;
border-radius: 50%;
background: #fff;
/*background: rgba(255, 255, 255, 0.2);*/
top: 1px;
left: 1px;
transition: all 0.3s ease;
}
input:checked + .slidinggroove {
background: #5fcf80;
}
input:checked + .slidinggroove:after {
transform: translateX(30px);
}
.labelterm {
margin-left: 65px;
font-size: 16px;
color: #222;
font-family: "Roboto", sans-serif;
position: relative;
top: 5px;
}
</style>
</head>
<body>
<div class="mylabel">
<input type="checkbox" id="coding">
<div class="slidinggroove"></div>
<label class="mylabel" for="coding" name="skills"><p class="labelterm">Test</p></label>
</div>
</body>
</html>
Here's how I would tackle this to achieve the look of the picture shown:
.slidinggroove::before{
position: absolute;
left: 7px;
top: 50%;
transform: translateY(-7px);
width: 20px;
height: 20px;
font-family: "Font Awesome 5 Free";
font-weight: 900;
content: "\f00c";
display: block;
color: #fff;
}
You must import a library for the icon as a font, I recommend using FontAwesome as shown in the working snippet here :
.mylabel {
position: relative;
display: block;
width: 60px;
height: 30px;
margin-bottom: 15px;
}
.mylabel input {
display: none;
}
.slidinggroove {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #ababab;
/*background: rgba(0, 0, 0, 0.1);*/
border-radius: 20px;
transition: all 0.3s ease;
}
.slidinggroove:after {
position: absolute;
content: "";
width: 28px;
height: 28px;
border-radius: 50%;
background: #fff;
/*background: rgba(255, 255, 255, 0.2);*/
top: 1px;
left: 1px;
transition: all 0.3s ease;
}
.slidinggroove:before {
position: absolute;
left: 7px;
top: 50%;
transform: translateY(-7px);
width: 20px;
height: 20px;
font-family: "Font Awesome 5 Free";
font-weight: 900;
content: "\f00c";
display: block;
color: #fff;
}
input:checked+.slidinggroove {
background: #5fcf80;
}
input:checked+.slidinggroove:after {
transform: translateX(30px);
}
.labelterm {
margin-left: 65px;
font-size: 16px;
color: #222;
font-family: "Roboto", sans-serif;
position: relative;
top: 5px;
}
<html>
<head>
<meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1">
<title>Awesome checkbox</title>
</head>
<body>
<div class="mylabel">
<input type="checkbox" id="coding">
<div class="slidinggroove"></div>
<label class="mylabel" for="coding" name="skills"><p class="labelterm">Test</p></label>
</div>
</body>
</html>
The way it works is as follow, you create a pseudo-element that will have as content the unicode of the fontawesome icon. Then you have a complete control hover it (font-size, color, ...).
Appreciate your eagerness of leaning. Let’s break the problem down and tackle each of them then merge them together to have a complete solution. Apparently, we need several things:
An oval shape background for the toggle to move. Lets call it pit
A circle that can be move to left or right. Lets call it knob.
The control need to have its own state, for checked and unchecked. We can make use of an native checkbox
The color of the control will change along the state.
Animation
We start with the basic first. To draw the toggle with html:
<div class="toggle">
<input class="toggle__input" type="checkbox"> <span class="toggle__pit"> <span class="toggle__knob"></span>
</span>
</div>
the toggle serve as the container of the whole toggle. Inside there is a a native checkbox element, toggle__pit and a toggle__knob. Without css they are just white square. Lets style it according to the sample image.
.toggle__pit {
/* set the size */
width: 36px;
height: 16px;
/* set the color */
background-color: #bababa;
border: 1px solid #bababa;
/* set the oval shape, value = height /2 */
border-radius: 8px;
/* border width is part of the element size */
box-sizing: border-box;
/* display span as a inline block element */
/* span is a inline element which cant assign width and height*/
display: inline-block;
}
.toggle__knob {
/* set the size */
width: 14px;
height: 14px;
/* make it circle */
border-radius: 50%;
background-color: white;
display: inline-block;
}
.toggle .toggle__input {
/* keep the checkbox hidden */
display: none;
}
<div class="toggle">
<input class="toggle__input" type="checkbox"> <span class="toggle__pit">
<span class="toggle__knob"></span>
</span>
</div>
Now the toggle looks like the sample image, but it is in unchecked state. We need to make it interactive so it responses to user action. Since the checkbox is hidden, user cannot interactive with it. We can use <label> to associate with the input. In this way even the input is hidden we can toggle it. We need to modify the html a bit, to have the input wrap by the label.
.toggle__pit {
/* set the size */
width: 36px;
height: 16px;
/* set the color */
background-color: #bababa;
border: 1px solid #bababa;
/* set the oval shape, value = height /2 */
border-radius: 8px;
/* border width is part of the element size */
box-sizing: border-box;
/* display span as a inline block element */
/* span is a inline element which cant assign width and height*/
display: inline-block;
}
.toggle .toggle__pit::after {
/* if the checkbox is checked, move knob to right */
content: 'L';
font-family: Helvetica, Arial, Sans-Serif;
color: white;
font-size: 12px;
display: inline-block;
transform: translateX(4px) translateY(-3px) scaleX(-1) rotate(-40deg);
transform-origin: 50% 50%;
}
.toggle__knob {
/* set the size */
width: 14px;
height: 14px;
/* make it circle */
border-radius: 50%;
background-color: white;
display: inline-block;
/* for position it to left or right */
position: absolute;
}
.toggle__label {
/* act as a reference point for knob positioning */
position: relative;
line-height: 16px;
}
.toggle .toggle__input {
/* keep the checkbox hidden */
display: none;
}
.toggle .toggle__input:checked+.toggle__pit {
/* if the checkbox is checked, change pit color */
background-color: #167ac6;
border: 1px solid #167ac6;
}
.toggle .toggle__input:checked+.toggle__pit .toggle__knob {
/* if the checkbox is checked, move knob to right */
left: 21px;
}
<div class="toggle">
<label class="toggle__label"> <input class="toggle__input" type="checkbox"> <span class="toggle__pit">
<span class="toggle__knob"></span>
</span>
</label>
</div>
Finally, to smoothen the state transition, add some transition to toogle__knob and toggle__pit.
.toggle__pit {
/* set the size */
width: 36px;
height: 16px;
/* set the color */
background-color: #bababa;
border: 1px solid #bababa;
/* set the oval shape, value = height /2 */
border-radius: 8px;
/* border width is part of the element size */
box-sizing: border-box;
/* display span as a inline block element */
/* span is a inline element which cant assign width and height*/
display: inline-block;
transition: background-color 0.5s linear, border 0.5s linear;
}
.toggle .toggle__pit::after {
/* use L to mock a tick*/
content: 'L';
font-family: Helvetica, Arial, Sans-Serif;
color: white;
font-size: 12px;
/* pseudo-element is inline by defauly, which you can't apply transform*/
display: inline-block;
/* flip L horizontally and rotate it */
transform: translateX(4px) translateY(-3px) scaleX(-1) rotate(-40deg);
transform-origin: 50% 50%;
}
.toggle__knob {
/* set the size */
width: 14px;
height: 14px;
/* make it circle */
border-radius: 50%;
background-color: white;
display: inline-block;
/* for position it to left or right */
position: absolute;
left: 1px;
/* enable animation */
transition: all 0.5s linear;
}
.toggle__label {
/* act as a reference point for knob positioning */
position: relative;
line-height: 16px;
}
.toggle .toggle__input {
/* keep the checkbox hidden */
display: none;
}
.toggle .toggle__input:checked+.toggle__pit {
/* if the checkbox is checked, change pit color */
background-color: #167ac6;
border: 1px solid #167ac6;
}
.toggle .toggle__input:checked+.toggle__pit .toggle__knob {
/* if the checkbox is checked, move knob to right */
left: 21px;
}
<div class="toggle">
<label class="toggle__label"> <input class="toggle__input" type="checkbox"> <span class="toggle__pit">
<span class="toggle__knob"></span>
</span>
</label>
</div>