how do I make a text like this show up once I hover over an image? some tumblr themes have this same feature too so i wonder how do you do it heres an example of what I mean
you can try this
.container{
width:200px;
height:200px;
text-align:center;
display:flex;
justify-content:center;
align-items:center;
position: relative;
}
.hide {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
img{
width:200px;
height:200px;
}
img:hover + .hide {
display: block;
}
.hide:hover{
animation: color-change 1s infinite;
}
#keyframes color-change {
0% { color: orange; }
50% { color: green; }
75% { color: yellow; }
100% { color: lightblue; }
}
<div class="container">
<img src="https://i.imgur.com/W0cq73T.jpg">
<div class="hide">this text will be shown when someone hovers the image</div>
</div>
so basically you set the text to display:none to hide the text.
And set it to display:block to show the text when someone hovers it, javascript is not needed at all
and now you can use the animation to animate the color of the text like in the video when someone hovers the text
let test = document.getElementById("test");
test.addEventListener("mouseover", function(event) {
// highlight the mouseover target
event.target.style.color = "orange";
// reset the color after a short delay
setTimeout(function() {
event.target.style.color = "";
}, 500);
}, false);
#center {
display: flex;
justify-content: center;
align-items: center;
height: 300px;
width: 300px;
background: url('https://www.iso.org/files/live/sites/isoorg/files/news/News_archive/2017/08/Ref2213/Ref2213.jpg/thumbnails/300x300');
color: #fff
}
<div id="center">
<p>Te<span id="test">ss</span>s</p>
</div>
Related
I am trying to create a tooltip for whatever that needs it on my website, e.g. a button, text, etc. So far I have something like this:
https://jsfiddle.net/f06q3cLg/
.content {
display: grid;
width: 100vw;
height: 100vh;
place-content: center;
}
.content .parent {
border: 1px red solid;
padding: 10px;
position: relative;
}
.content .parent:hover .tooltip-wrapper {
animation: 0.1s fadeInTooltip;
animation-fill-mode: forwards;
animation-delay: 0.4s;
}
.content .parent:hover:before {
animation: 0.1s fadeInTooltip;
animation-fill-mode: forwards;
animation-delay: 0.4s;
}
.content .parent:active .tooltip-wrapper {
animation: 0.05s fadeOutTooltip;
animation-fill-mode: forwards;
}
.content .parent:active:before {
animation: 0.05s fadeOutTooltip;
animation-fill-mode: forwards;
}
.content .parent:before {
content: "";
display: block;
width: 0;
height: 0;
position: absolute;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
left: 50%;
transform: translateX(-50%);
opacity: 0;
}
.content .parent .tooltip-wrapper {
position: absolute;
display: grid;
left: 0;
width: 300px;
height: 100%;
opacity: 0;
pointer-events: none;
}
.content .parent .tooltip-wrapper.bottom {
top: calc(100% + 8px);
}
.content .parent .tooltip-wrapper .tooltip {
max-width: 300px;
width: fit-content;
padding: 8px;
position: absolute;
display: inline-block;
background: blue;
border-radius: 5px;
padding: 8px;
color: white;
font-size: 11px;
box-shadow: 0px 3px 3px rgba(0, 0, 0, 0.2);
line-height: 1.3;
text-align: left;
}
/* Keyframes */
#keyframes fadeInTooltip {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeOutTooltip {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
<div class="content">
<div class="parent">
Hover me
<div class="tooltip-wrapper">
<span class="tooltip">This is my tooltip</span>
</div>
</div>
</div>
As such, it works somewhat fine. My issue is that I would like the tooltip to disappear when I click the button. Now it vanishes, and then comes back with a 0.4s delay as the hover effect actually has. Ideally the tooltip should disappear as long as my mouse is still on the button, but when I remove it and re-enters the button, then the tooltip should re-appear.
I'm not sure if this is even achievable with pure CSS, but any JS would also do.
The problem is that :active is only applied as long as the mouse is down.
mdn: :active:
The :active CSS pseudo-class represents an element (such as a button) that is being activated by the user. When using a mouse, "activation" typically starts when the user presses down the primary mouse button.
What you could do (if you want to stay CSS only) is to use tabindex="0" on the <div class="parent"> and :focus instead of :active. But you need to verify that using tabindex="0" here won't hurt usability.
Ideally the tooltip should disappear as long as my mouse is still on the button, but when I remove it and re-enters the button, then the tooltip should re-appear.
That won't work with :focus either. I'm pretty sure that this behavior can only be achieved with JS. If it is possible with CSS only it likely would be a pretty hacky solution.
But from the perspective of a user, this seems to be counterintuitive that the tooltip won't appear after clicked.
A JavaScript solution that does what you want could look like this.
It is a simplified version of the tooltip to only show the relevant parts.
Every element having a tooltip has an attribute data-has-tooltip.
// event delegation for all mouse down event:
// this ensures that the code also works for elements that have been added to the DOM after that script was executed.
document.addEventListener('mousedown', (evt) => {
// check if the mousedown happened in an element with a tooltip
const element = evt.target.closest('[data-has-tooltip]');
if (element) {
// if the user already clicked on the element ignore the click
if (!element.classList.contains('active')) {
// add the active class to the element so that hover won't show the toolip
element.classList.add('active');
function removeActiveOnLeave() {
// remove the active class
element.classList.remove('active');
// remove the mouseleave event listener again
element.removeEventListener('mouseleave', removeActiveOnLeave)
}
// add an event listener for mouseleave to remove the active class
element.addEventListener('mouseleave', removeActiveOnLeave)
}
}
});
.parent {
display: inline-block;
border: 1px solid red;
padding: 0.5rem;
margin: 0.5rem;
}
.tooltip-wrapper {
display: none;
}
.parent:hover .tooltip-wrapper {
display: block;
}
.parent.active:hover .tooltip-wrapper {
display: none;
}
<div class="content">
<div class="parent" data-has-tooltip>
Hover me A
<div class="tooltip-wrapper">
<span class="tooltip">This is my tooltip A </span>
</div>
</div>
</div>
<div class="content">
<div class="parent" data-has-tooltip>
Hover me B
<div class="tooltip-wrapper">
<span class="tooltip">This is my tooltip B</span>
</div>
</div>
</div>
HTML
<div class="content">
<div class="parent" onClick="myFunction()">
Hover me
<div class="tooltip-wrapper">
<span class="tooltip" id="tooltip">This is mytooltip</span>
</div>
</div>
</div>
Javascript
function myFunction(){
var tooltip=document.getElementById("tooltip");
if (tooltip.style.display=="none") {
document.getElementById("tooltip").style.display="block";
} else {
document.getElementById("tooltip").style.display="none";
}
}
Manipulating 'display' property.
const parent = document.querySelector('.parent');
const toolTip = document.querySelector('.tooltip');
parent.addEventListener('click', () => {
if(toolTip.style.display !== 'none') {
toolTip.style.display = 'none';
}else {
toolTip.style.display = 'grid';
}
});
A solution using jQuery 3.4.1:
$(".parent").click(function () {
$(".tooltip-wrapper").css("display", "none");
});
The only downfall with that solution is once you click and re-hover in the same session, the SCSS :hover doesn't work properly.
No need to stress, just add the following if you want that functionality:
$(".parent").hover(function () {
$(".tooltip-wrapper").css("display", "block");
});
Try it out in the attached snippet:
$(".parent").click(function () {
$(".tooltip-wrapper").css("display", "none");
});
$(".parent").hover(function () {
$(".tooltip-wrapper").css("display", "block");
});
.content {
display: grid;
width: 100vw;
height: 100vh;
place-content: center;
}
.content .parent {
border: 1px red solid;
padding: 10px;
position: relative;
}
.content .parent:hover .tooltip-wrapper {
animation: 0.1s fadeInTooltip;
animation-fill-mode: forwards;
animation-delay: 0.4s;
}
.content .parent:hover:before {
animation: 0.1s fadeInTooltip;
animation-fill-mode: forwards;
animation-delay: 0.4s;
}
.content .parent:active .tooltip-wrapper {
animation: 0.05s fadeOutTooltip;
animation-fill-mode: forwards;
}
.content .parent:active:before {
animation: 0.05s fadeOutTooltip;
animation-fill-mode: forwards;
}
.content .parent:before {
content: "";
display: block;
width: 0;
height: 0;
position: absolute;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
left: 50%;
transform: translateX(-50%);
opacity: 0;
}
.content .parent .tooltip-wrapper {
position: absolute;
display: grid;
left: 0;
width: 300px;
height: 100%;
opacity: 0;
pointer-events: none;
}
.content .parent .tooltip-wrapper.bottom {
top: calc(100% + 8px);
}
.content .parent .tooltip-wrapper .tooltip {
max-width: 300px;
width: fit-content;
padding: 8px;
position: absolute;
display: inline-block;
background: blue;
border-radius: 5px;
padding: 8px;
color: white;
font-size: 11px;
box-shadow: 0px 3px 3px rgba(0, 0, 0, 0.2);
line-height: 1.3;
text-align: left;
}
/* Keyframes */
#keyframes fadeInTooltip {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeOutTooltip {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<div class="parent">
Hover me
<div class="tooltip-wrapper">
<span class="tooltip">This is my tooltip</span>
</div>
</div>
</div>
OR, you can see it working in this Fiddle. with your initial
SCSS.
You can uncomment the second function to see the hover working again after clicking.
So, I have an image in the middle of the page (where I want it to remain) and while I hold the LMB I want it to get a little bit smaller, then go back to its previous size when released.
Below the code:
$(document).ready(function() {
$("#banana").mousedown(function() {
$("#banana").css("height","70%");
});
$("#banana").mouseup(function() {
$("#banana").css("height","100%");
});
});
.centered {
text-align: center;
display: block;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div id = "banana" class = "centered">
<img src="https://via.placeholder.com/150" alt="banana.png">
</div>
</body>
I tried get that target using jQuery (but the position of the image changes and it is not centred anymore).
Thanks in advance!
This is very easy to do with CSS only, using the :active pseudo-selector (that corresponds to "mousedown"). Also why not use Flex for easy centering.
.container {
border: #00f solid 1px;
width: 250px;
height: 250px;
display: flex;
justify-content: center;
align-items: center;
}
.container img {
transition: all 0.3s ease-in-out;
transform: scale(1);
}
.container img:active {
transform: scale(0.8);
}
<div class="container"><img src="https://via.placeholder.com/150"/></div>
Try
transform: scale(0.7)
instead of height. It will be centered and it's more efficient (GPU usage)
place the LMB on the image not the div and use width not height
$(document).ready(function() {
$("#pic").mousedown(function() {
$("#pic").css("width","70%");
});
$("#pic").mouseup(function() {
$("#pic").css("width","100%");
});
});
.centered {
text-align: center;
display: block;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div id = "banana" class = "centered">
<img id='pic' src="https://picsum.photos/300" alt="banana.png">
</div>
</body>
Add and remove a class to your body and transform your image indirectly:
$(document).ready(function() {
const body = $('body');
const cssClassClicked = 'lmb-clicked';
body
.mousedown(function() {
body.toggleClass(cssClassClicked)
})
.mouseup(function() {
body.toggleClass(cssClassClicked)
});
});
body {
min-height: 100vh;
background: #eee;
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
}
.img {
display: block;
transition: transform 300ms ease-in-out;
will-change: transform;
}
.lmb-clicked .img {
transform: scale(0.9);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<img class="img" src="https://picsum.photos/id/1/400/300">
This should work:
$(document).ready(function() {
$("#banana").mousedown(function() {
$("#banana").css("height","50vh");
});
$("#banana").mouseup(function() {
$("#banana").css("height","100vh");
});
});
.centered {
text-align: center;
display: block;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<body>
<div class = "centered">
<img id = "banana" src="https://www.chiquita.com/wp-content/uploads/2019/12/Chiquita_Banana_Class_Extra_Yellow.jpg" alt="banana.png">
</div>
</body>
Ultimately, for each click of a button, I want to display an element that contains new content. In other words...
You read content contained within a parent container
To see the next item click the button
When the button is clicked, the old content shifts downward. The new content flows down from the top of the container. It pauses in order to read the new content.
To get new content, press the button again.
I'm unclear as to how to accomplish this, and if it's even possible with a CSS Animation. With what I have posted, it just takes both elements and translates them down the vertical axis at once. How can this be refactored so that one element pauses and displays it's content using just vanilla JavaScript?
var div1 = document.querySelector(".first");
var div2 = document.querySelector(".second");
var button = document.querySelector("button");
var divs = [div1, div2];
button.addEventListener("click", function(event) {
event.preventDefault();
for (var i = divs.length - 1; i > -1; i--) {
var div = divs[i];
div.classList.remove("down_shift");
void div.offsetWidth;
div.classList.add("down_shift");
}
});
body {
background: #222;
}
section {
width: 50vw;
height: 300px;
border: 5px solid red;
margin: 50px auto;
overflow: hidden;
}
.first, .second {
width: inherit;
height: 300px;
background: red;
transform: translateY(-300px);
}
.second {
background: pink;
}
h1 {
margin: 0;
padding-top: 50px;
text-align: center;
}
.down_shift {
animation: down 1s ease-out;
}
#keyframes down{
from {
transform: translateY(0);
}
to {
transform: translateY(300px);
}
}
<section>
<div class="first"><h1>1</h1></div>
<div class="second"><h1>2</h1></div>
</section>
<button type="button">Click</button>
You can add a wrapper to the elements, and animate the wrapper
var wrapper = document.querySelector(".wrapper");
var button = document.querySelector("button");
button.addEventListener("click", function(event) {
event.preventDefault();
wrapper.style.transform = 'translateY(-300px)'
});
body {
background: #222;
}
section {
width: 50vw;
height: 300px;
border: 5px solid red;
margin: 50px auto;
overflow: hidden;
}
.first, .second {
width: inherit;
height: 300px;
background: red;
/* transform: translateY(-300px); */
}
.second {
background: pink;
}
.wrapper {
transition: all 1s ease-out;
}
h1 {
margin: 0;
padding-top: 50px;
text-align: center;
}
.down_shift {
animation: down 1s ease-out;
}
#keyframes down{
from {
transform: translateY(0);
}
to {
transform: translateY(300px);
}
}
<section>
<div class="wrapper">
<div class="first"><h1>1</h1></div>
<div class="second"><h1>2</h1></div>
</div>
</section>
<button type="button">Click</button>
There are similar questions like this and this, but don't address this situation.
The goal is to slide a menu onto the screen with CSS translation when its parent is shown. However, showing the parent then applying the CSS class to trigger the translation happens instantly instead of over time. Effectively, there's no animation.
JavaScript could be used to slide the child element onto the screen, but the goal is to keep as much of the animation logic in CSS.
Setting the opacity to 0 doesn't work because we need the menu and its parent to not take any space or be part of the layout.
Codepen: https://codepen.io/Crashalot/pen/YzXmjYj
function toggleSidebar() {
$("#sidebar").toggleClass("show");
}
$("#button").on("click", function() {
toggleSidebar();
});
body {
margin: 0;
padding: 0;
}
#button {
position: fixed;
top: 0;
left: 200px;
width: 150px;
height: 50px;
background: yellow;
display: flex;
justify-content: center;
align-items: center;
z-index: 8;
cursor: pointer;
}
#sidebar {
display: none;
}
#sidebar.show {
display: block;
}
.overlay {
position: fixed;
width: 100vw;
height: 100vh;
background: red;
z-index: -1;
}
.menuBox {
width: 200px;
height: 100vh;
background: blue;
transition: 0.3s ease-in-out;
transform: translate(-100%);
}
#sidebar.show .menuBox {
transform: translate(0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="sidebar">
<div class="overlay"></div>
<div class="menuBox"></div>
</div>
<div id="button">CLICK ME</div>
You can't animate display: none; Set opacity to 0 and then 1 on toggle class. Here's the CodePen for you. ;)
I added a button for the toggle event. Let me know if you need any more help!
enter link description here
$(".btn").on("click", toggleSidebar);
function toggleSidebar() {
$("#sidebar").toggleClass("show");
}
body {
margin: 0;
padding: 0;
}
#sidebar {
opacity: 0;
transition: all 300ms ease-in-out;
}
#sidebar.show {
display: block;
opacity: 1;
}
.overlay {
position: fixed;
width: 100vw;
height: 100vh;
background: red;
z-index: -1;
}
.menuBox {
width: 200px;
height: 100vh;
background: blue;
transition: 300ms ease-in-out;
-webkit-transform: translate(-100%);
}
#sidebar.show .menuBox {
-webkit-transform: translate(0);
}
.btn {
position: absolute;
top: 10px;
left: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="sidebar">
<div class="overlay"></div>
<div class="menuBox"></div>
</div>
<button class="btn">Click</button>
You need to consider an animation. The animation will run automatically when the element appear on the screen
function toggleSidebar() {
$("#sidebar").toggleClass("show");
}
$("#button").on("click", function() {
toggleSidebar();
});
body {
margin: 0;
padding: 0;
}
#button {
position: fixed;
top: 0;
left: 200px;
width: 150px;
height: 50px;
background: yellow;
display: flex;
justify-content: center;
align-items: center;
z-index: 8;
cursor: pointer;
}
#sidebar {
display: none;
}
#sidebar.show {
display: block;
}
.overlay {
position: fixed;
width: 100vw;
height: 100vh;
background: red;
z-index: -1;
}
.menuBox {
width: 200px;
height: 100vh;
background: blue;
transform: translate(-100%);
animation: show 0.3s ease-in-out forwards;
}
#keyframes show {
to {
transform: translate(0);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="sidebar">
<div class="overlay"></div>
<div class="menuBox"></div>
</div>
<div id="button">CLICK ME</div>
updating display to a value other than none will start all animations applied to the element by the animation-name property, as well as all animations applied to descendants with display other than none. ref
I think you should define the action for your function called. When load page or on click like below:
$(document).ready(function () {
$('#sidebar').on('click', function () {
$(this).toggleClass('show');
});
});
I have this simple HTML DIV where the word "Loading" is in the middle.
I also have the JavaScript code to change the dots in the #waitDotDotDot element.
var dots = window.setInterval( function() {
var wait = document.getElementById("waitDotDotDot");
if ( wait.innerHTML.length > 5 )
wait.innerHTML = "";
else
wait.innerHTML += ".";
}, 300);
<div style="width: 90%; text-align:center; margin-right:auto; margin-left:auto; border: 1px solid black;">
<div style="margin-right:auto; margin-left:auto; width:90%;">
Loading <span id="waitDotDotDot">.</span>
</div>
</div>
This is working, but it keeps resizing the "Loading" text (pushing it to the left) when the numbers of dots is increasing. Is there a way to keep the "Loading" text in the same position (still center), but only the dots are resizing while it is increasing?
For this kind of effect, personally I'd forego the script to keep it simple and solve the issue at the same time.
.container {
border: green 1px dashed;
}
.dotme {
margin-left: calc(50% - 4rem);
transform: translateX(-50%);
display: inline;
font-size: 2rem;
border: red 1px dotted;
}
.dotme:after {
content: "\2026";
display: inline-block;
width: 0;
overflow: hidden;
vertical-align: bottom;
animation: dots steps(4,end) .75s infinite alternate;
}
#keyframes dots {
to { width: 3rem;}
}
<div class="container">
<aside class="dotme">Loading</aside>
</div>
I modified Chris W.'s post to achieve the desired result.
.divWrapper {
width: 100%;
text-align: center;
}
.loading {
font-size: 2rem;
display: inline-block;
}
.dots {
visibility: hidden;
position: relative;
}
.dots::before {
content: "\2026";
visibility: visible;
display: inline-block;
position: absolute;
width: 0;
overflow: hidden;
vertical-align: bottom;
animation: dots steps(4,end) 1s infinite forwards;
}
#keyframes dots {
to { width: 2.5rem;}
}
<div class="divWrapper">
<p class="loading">
Loading<span class="dots">…</span>
</p>
</div>