Liquid filling text with animation - javascript

I am trying to get a CSS animation to make a text like it's filling with liquid. I've followed an example (Filling water animation) but what I need is doing the same with a text, not a circle.
Can I do it only using CSS? I don't need to correlate percentaje text with how much does the text fills. I mean, if I write 73% I don't need to automatically fill until 73% capacity.
#banner {
width: 300px;
height: 300px;
position: relative;
background: #ccc;
border-radius: 50%;
overflow: hidden;
}
#banner::before {
content: '';
position: absolute;
background: #ff0019;
width: 100%;
bottom: 0;
animation: wipe 5s cubic-bezier(.2,.6,.8,.4) forwards;
}
#keyframes wipe {
0% {
height: 0;
}
100% {
height: 73%;
}
}
<div id="banner">73%</div>

Here is text that fills like liquid.
Works great in Chrome but needs tweaking in Firefox.
#banner {
position: relative;
overflow: hidden;
font-family: sans-serif;
font-size: 40pt;
font-weight: bold;
background: #ccc
}
.inner {
background: #000;
color:#fff;
mix-blend-mode: multiply;
}
#banner::before {
content: '';
position: absolute;
background: #0f0;
width: 100%;
bottom: 0;
animation: wipe 5s cubic-bezier(.2,.6,.8,.4) forwards;
}
#keyframes wipe {
0% {
height: 0;
}
100% {
height: 73%;
}
}
<span id="banner">
<span class="inner">73%</span>
</span>

Related

Transition going only one way when removing class

I'm trying to create a sidebar like this:
function show_menu(){
document.querySelector('#sidebar').classList.toggle('sidebar_open');
document.querySelector('#blackscreen').classList.toggle('blackscreen_open');
}
#hamburger {
width: 5rem;
height: 5rem;
background-color: red;
}
#header_wrapper {
display: block;
}
#sidebar {
position: fixed;
top: 0;
right: 0;
width: 0;
height: 100vh;
transition: width 0.25s;
}
.sidebar_open {
width: 50% !important;
background-color: green;
display: grid !important;
}
#blackscreen{
position:fixed;
top:0;
right:0;
width:100vw;
height:100vh;
transition: background-color 0.25s;
}
.blackscreen_open {
background-color: rgba(0, 0, 0, 0.5);
}
<div id="hamburger" onclick="show_menu()">click here</div>
<div id='blackscreen' onclick="show_menu()"></div>
<span id='sidebar'>
</span>
but the sidebar transition only works one way,
My best guess is that the transition requires 2 classes to operate
but since I've removed one class the transition back might not be taking place
so I tried the solution according to this question like this:
function show_menu(){
document.querySelector('#sidebar').classList.toggle('sidebar_open');
document.querySelector('#blackscreen').classList.toggle('blackscreen_open');
}
#hamburger {
width: 5rem;
height: 5rem;
background-color: red;
}
#header_wrapper {
display: block;
}
#sidebar {
position: fixed;
top: 0;
right: 0;
width: 0;
height: 100vh;
}
#sidebar:not(.sidebar_open) {
transition: width 0.25s;
}
.sidebar_open {
width: 50% !important;
background-color: green;
display: grid !important;
}
#blackscreen {
position: fixed;
top: 0;
right: 0;
width: 100vw;
height: 100vh;
transition: background-color 0.25s;
}
.blackscreen_open {
background-color: rgba(0, 0, 0, 0.5);
}
<div id="hamburger" onclick="show_menu()">click here</div>
<div id='blackscreen' onclick="show_menu()"></div>
<span id='sidebar'>
</span>
but as you can see even that didn't work
I'm pretty sure I'm missing something obvious but any & all help is greatly appreciated!
I'm fairly certain that the transition IS working but you're not seeing it because when it's not open, your sidebar doesn't have a background colour, and since you don't have a transition setting for your background attribute, when you remove the sidebar_open class the background colour IMMEDIATELY reverts to none and the width transition becomes invisible.
You should be able to test this by moving background-color: green; from the .sidebar_open class to the #sidebar element.
You need to have the background-color set even when the sidebar is not open. Otherwise, when the class is removed, you can no longer see it even though the width is being animated.
#sidebar {
position: fixed;
top: 0;
right: 0;
width: 0;
height: 100vh;
background-color: green;
transition: width 0.25s;
}
function show_menu() {
document.querySelector('#sidebar').classList.toggle('sidebar_open');
document.querySelector('#blackscreen').classList.toggle('blackscreen_open');
}
#hamburger {
width: 5rem;
height: 5rem;
background-color: red;
}
#header_wrapper {
display: block;
}
#sidebar {
position: fixed;
top: 0;
right: 0;
width: 0;
height: 100vh;
background-color: green;
transition: width 0.25s;
}
.sidebar_open {
width: 50% !important;
display: grid !important;
}
#blackscreen {
position: fixed;
top: 0;
right: 0;
width: 100vw;
height: 100vh;
transition: background-color 0.25s;
}
.blackscreen_open {
background-color: rgba(0, 0, 0, 0.5);
}
<div id="hamburger" onclick="show_menu()">click here</div>
<div id='blackscreen' onclick="show_menu()"></div>
<span id='sidebar'></span>

Mobile menu - CSS / DIV - Dim visible background around menu?

When my mobile menu opens, I would love the rest of the visible background (other than the menu itself) to 'dim.' (Both my pages and menu background are very white in general).
There is a plugin that offers this functionality but in trying to keep the website light, am trying to see if this is possible with just some lines of code?
Googling for quite a while came up with nothing other than the app which is a surprise... maybe I searched the wrong keywords?
Any ideas?
Here is my full code (not my original code, can link various parts to their respective Authors).
/*Change hamburger menu colour*/
span.mobile_menu_bar:before{
color:#D7AF39;
}
/*Remove shading of top menu to match sub menu*/
.et_mobile_menu .menu-item-has-children a {
background-color:#FFFFFF;
}
/** Divi Space slide in mobile edits**/
#mobile_menu { display: block !important; min-height: 100vh; top: 0; border-top: none; padding-top: 80px; z-index: 9998; }
.mobile_nav.closed #mobile_menu {
transform: rotateY(90deg); -webkit-transform: rotateY(90deg);
transform-origin: right; -webkit-transform-origin: right;
background: #fff; transition: .8s ease-in-out !important; }
.mobile_nav.opened #mobile_menu {
transform: rotateY(0deg); -webkit-transform: rotateY(0deg);
transform-origin: right; -webkit-transform-origin: right;
background: #fff; transition: .8s ease-in-out; }
.mobile_nav.opened .mobile_menu_bar:before {
content: "\4d"; color: #D7AF39; }
.et_mobile_menu li a, .et_mobile_menu .menu-item-has-children>a {
font-weight: 600;
font-family: open sans;
font-size: large;
}
#media(max-width: 980px) {
.et_header_style_split .mobile_menu_bar, .et_header_style_left .mobile_menu_bar { z-index: 9999; }
#main-header .container.clearfix.et_menu_container { width: 100%; }
.logo_container { padding-left: 30px; }
#et-top-navigation { padding-right: 30px; }
}
#media(min-width: 341px) {
#mobile_menu { width: 340px; margin-left: calc(100% - 340px); }
}
One way of doing this is to assert a blanket div over the entire page, beginning just below the menu bar, then setting that div's opacity to the desired level of dimming.
I have thrown together a very simple proof of concept. Hover the dummy Menu button to observe the effect. Take it onwards from there.
body {
--menu-height: 50px;
}
#page {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: yellow;
}
#menu_bar {
position: absolute;
width: 100%;
height: var( --menu-height);
background-color: blue;
}
#menu_item {
position: absolute;
top: 10px;
left: 10px;
width: 50px;
height: 30px;
background-color: white;
line-height: 30px;
text-align: center;
}
#menu_item:hover:after {
content: '';
position: fixed;
top: var( --menu-height);
left: 0;
height: 100vh;
width: 100vw;
background-color: black;
opacity: 0.5;
/* Ensure z-index is higher than page's content/data items */
z-index: 2
}
#data {
position: absolute;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
background-color: white;
border: 2px solid black;
padding: 10px;
z-index: 1;
}
#text {
display: inline-block;
width: 100%;
text-align: center;
font-weight: bold;
}
<div id="page">
<div id="menu_bar">
<div id="menu_item">Menu</div>
</div>
<div id="data">
<span id="text">Hover the "Menu" button...</span><br><br> Lorem ipsum dolor etc
</div>
</div>

Text fill effect - simulate a block of color passing through text

I'm trying to create a text effect so when you hover over text, a block of color seems to pass through the text.
I followed exactly what the first example here (for the word "Kukuri") does by using a :before pseudo-element to achieve the color fill. I have the code written here in SCSS:
.text {
position: relative;
&:hover {
&:before {
width: 100%;
}
}
&:before {
content: 'HELLO'; // if our text was "HELLO"
width: 0%;
position: absolute;
z-index: 2;
overflow: hidden;
color: red;
transition: width 350ms ease-in-out;
white-space: nowrap;
width: 0%;
}
}
However, I'm wondering if it's possible to animate the :before element's width the other way? So once it hits 100% width and fills with color, then the left side starts emptying and it goes back to 0% fill.
The end goal is to use this for a navigation menu. Something like this effect where it seems like a block of color is moving through menu items when you hover:
For something like this, hovering over "About" item would make the fill color wipe down while
Attempted Solutions
I tried translating the :before element, changing the left and right properties, and changing transform-origin to no avail.
I've tried looking into mix-blend-mode to try and create a rectangular mask that could potentially add color to the text. However, to my understanding, mix-blend-mode only works with text and not with rectangular divs with background-colors.
You may do something like this by simply using a layer that pass above your element with transparent background:
ul {
list-style: none;
padding: 0;
margin: 0;
}
ul li {
display: inline-block;
margin: 10px;
position: relative;
font-size: 30px;
color: red;
font-weight: bold;
overflow: hidden;
}
ul li:before {
content: "";
position: absolute;
height: 100%;
width: 100%;
background: rgba(255, 255, 255, 0.6);
transition: 2s;
z-index: 2;
}
ul.ver li:before {
top: 0;
left: -100%;
}
ul.hor li:before {
top: -100%;
left: 0;
}
ul.ver li:hover::before {
left: 100%;
}
ul.ver.half li:hover::before {
left: 0;
}
ul.hor li:hover::before {
top: 100%;
}
ul.hor.half li:hover::before {
top: 0;
}
<ul class="hor">
<li>Home</li>
<li>About</li>
</ul>
<ul class="hor">
<li>Home</li>
<li>About</li>
</ul>
<ul class="ver half">
<li>Home</li>
<li>About</li>
</ul>
<ul class="hor half">
<li>Home</li>
<li>About</li>
</ul>
And here is another example using mix-blend-mode with text:
ul {
list-style: none;
padding: 0;
margin: 0;
}
ul li {
display: inline-block;
margin: 10px;
position: relative;
font-size: 30px;
background-image: linear-gradient(to right, red, red);
background-size: 200% 200%;
background-repeat: no-repeat;
font-weight: bold;
overflow: hidden;
transition: 1s;
}
ul.hor li {
background-position: 0% 200%;
}
ul.ver li {
background-position: 200% 0%;
}
ul li span {
display: inline-block;
color: black;
background-color: white;
mix-blend-mode: screen;
}
ul.hor li:hover {
background-position: 0% -100%;
}
ul.ver li:hover {
background-position:-100% 0%;
}
ul.hor.half li:hover {
background-position: 0% 0%;
}
ul.ver.half li:hover {
background-position:0% 0%;
}
<ul class="hor">
<li><span>Home</span></li>
<li><span>About</span></li>
</ul>
<ul class="ver">
<li><span>Home</span></li>
<li><span>About</span></li>
</ul>
<ul class="hor half">
<li><span>Home</span></li>
<li><span>About</span></li>
</ul>
<ul class="ver half">
<li><span>Home</span></li>
<li><span>About</span></li>
</ul>
You can use blend modes for this effect, here you have one posibility:
I opted for moving the background of the pseudo rather than moving the pseudo itself, This way you won't have side effects when the pseudo is over other elements.
Also, it isn't clear for me if you want a single slide or a double one. I have set it to be a double one ( from black to red and again to black. You can change this easily adjusting the final background position
.demo {
background-color: yellow;
margin: 10px;
display: inline-block;
font-size: 50px;
padding: 10px;
position: relative;
}
.demo:after {
content: "";
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background-image: linear-gradient(to right, transparent 25%, red 25%, red 75%, transparent 75% );
mix-blend-mode: lighten;
background-size: 400% 100%;
transition: background-position 2s linear;
background-position: 100% 0%;
}
.demo:hover:after {
background-position: 0% 0%;
}
<div class="demo">TEST1</div>
<div class="demo">TEST2</div>
To change the movement to vertical, you need to change
the gradient direction
which of the image dimensions is oversized
the background position that is changed on hover
.demo {
background-color: yellow;
margin: 10px;
display: inline-block;
font-size: 50px;
padding: 10px;
position: relative;
}
.demo:after {
content: "";
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background-image: linear-gradient(to top, transparent 25%, red 25%, red 75%, transparent 75% );
mix-blend-mode: lighten;
background-size: 100% 400%; /* changed vertical dimension */
transition: background-position 2s linear;
background-position: 0% 100%; /* changed 100 position to vertical*/
}
.demo:hover:after {
background-position: 0% 0%;
}
<div class="demo">TEST1</div>
<div class="demo">TEST2</div>
.text {
text-transform: uppercase;
font-weight: 900;
overflow: hidden;
line-height: 0.75;
color: #c5c2b8;
position:relative;
}
.text:before {
content: attr(data-letters);
position: absolute;
z-index: 2;
overflow: hidden;
color: red;
white-space: nowrap;
width: 0%;
top:0;
-webkit-transition: width 0.4s 0.3s;
transition: width 0.4s 0.3s;
}
.text:hover:before {
width: 100%;
}
<span class="text" href="#" data-letters="hello">hello</span>

How to morph a plus sign to a minus sign using CSS transition?

I want to create a toggle button that morphs its shape from a plus sign to a minus sign.
Using CSS only, without the use of pseudo-elements.
My desired effect is to have the vertical line in the "+" sign to shrink into the horizontal line.
I know it's possible but I'm not sure which is the best route to take. I was thinking of doing something with the height but I'm worried about the line-height of browsers changing its position in the element.
$('button').on("click", function(){
$(this).toggleClass('active');
});
button {
color: #ecf0f1;
background: #e74c3c;
width: 50px;
height: 50px;
border: 0;
font-size: 1.5em;
}
button span {
transition: all .75s ease-in-out;
}
button.active span {
/* Code to morph + to - */
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button><span>+</span></button>
Because of the simplicity of the shapes, the easiest way is just to make the + and - with elements. Using pseudo elements would be the cleanest solution, but you can also just use a DOM element and have a slightly messier document structure.
With that in mind, the actual solution is straightforward. We use CSS to position elements to resemble the desired characters, and then "morph" between them by animating that position.
Take a look over the following code, and try to understand what each rule is accomplishing.
button {
color: #ecf0f1;
background: #e74c3c;
width: 50px;
height: 50px;
border: 0;
font-size: 1.5em;
position: relative;
}
button span {
position: absolute;
transition: 300ms;
background: white;
border-radius: 2px;
}
/* Create the "+" shape by positioning the spans absolutely */
button span:first-child {
top: 25%;
bottom: 25%;
width: 10%;
left: 45%;
}
button span:last-child {
left: 25%;
right: 25%;
height: 10%;
top: 45%;
}
/* Morph the shape when the button is hovered over */
button:hover span {
transform: rotate(90deg);
}
button:hover span:last-child {
left: 50%;
right: 50%;
}
<button>
<span></span>
<span></span>
</button>
Note : please stop editing the question making the answers incorrect
CSS solution
$('button').on("click", function(){
$(this).toggleClass('active');
});
button {
color: #ecf0f1;
background: #e74c3c;
width: 70px;
height: 70px;
position: relative;
font-size: 50px;
cursor: pointer;
border: 0;
outline: 0;
padding: 0
}
.plus,
.minus {
color: #fff;
padding: 10px;
width: 70px;
height: 70px;
line-height: 50px;
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
text-align: center;
box-sizing: border-box;
transition: .5s all ease-out;
}
.plus {
opacity: 1;
transform: rotate(0deg);
}
button.active .plus {
opacity: 0;
transform: rotate(90deg);
}
.minus {
opacity: 0;
transform: rotate(-90deg);
}
button.active .minus {
opacity: 1;
transform: rotate(0deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" />
<button>
<span class="plus"><i class="fa fa-plus"></i></span>
<span class="minus"><i class="fa fa-minus"></i></span>
</button>
A (old) CSS solution:
Using pseudo element ::before with content property
$('button').on("click", function() {
$(this).toggleClass('active');
});
button {
color: #ecf0f1;
background: #e74c3c;
width: 50px;
height: 50px;
border: 0;
font-size: 1.5em;
}
button span {
transition: all .75s ease-in-out;
position:relative
}
button span::before {
content:"+"
}
button.active span::before {
content:"-"
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button><span></span></button>
A (old) jquery Solution:
no need for span, you can do this using text() with a if statement in jquery
$('button').on("click", function() {
$(this).toggleClass('active');
$(this).text() == "+" ? $(this).text("-") : $(this).text("+");
});
button {
color: #ecf0f1;
background: #e74c3c;
width: 50px;
height: 50px;
border: 0;
font-size: 1.5em;
transition: all .75s ease-in-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button>+</button>
Ah my bad I've overlooked that OP doesn't want to use any pseudo
elements. But the big advantage with pseudo elements would be that you have less HTML Code and a cleaner structure.
It's also a different morphing animation as OP wants but maybe someone else can use this.
So if you don't mind I'll let my suggestion there.
Maybe something like this?
HTML
<div class="button"></div>
CSS
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
}
body {
margin: 0;
background: #343838;
}
.button {
position: absolute;
width: 55px;
height: 55px;
background: #70975B;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(0deg);
border-radius: 50%;
cursor: pointer;
z-index: 100;
transition: 0.4s cubic-bezier(0.2, 0.6, 0.3, 1.1);
}
.button:after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
height: 2px;
width: 50%;
background: white;
}
.button:before {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
height: 50%;
width: 2px;
background: white;
}
.button.clicked {
transform: translate(-50%, -50%) rotate(360deg);
background: #CC2A41;
}
.button.clicked:before {
width: 0;
}
jQuery
$(".button").click(function() {
$(this).toggleClass("clicked");
});
And here a working example
http://codepen.io/svelts/pen/LkyZoZ
try this
$('button').on("click", function() {
var $this = $(this);
$this.toggleClass('toggle');
if ($this.hasClass('toggle')) {
$this.text('+');
} else {
$this.text('-');
}
});
button {
color: #ecf0f1;
background: #e74c3c;
width: 50px;
height: 50px;
border: 0;
font-size: 1.5em;
transition: all .75s ease-in-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button class="toggle">+</button>

Code not working in IE and Edge

I have a script that works perfectly in Chrome, but the CSS does not work in Edge and the scrolling text does not work in IE10.
See how it should work in Chrome (please allow about 5 seconds for the scrolling text to start:
https://jsfiddle.net/oxw4e5yh/
CSS:
<style>
/* Make it a marquee */
.marquee {
width: 100%;
left: 0px;
height: 10%;
position: fixed;
margin: 0 auto;
white-space: nowrap;
overflow: hidden;
background-color: #000000;
bottom: 0px;
color: white;
font: 50px'Verdana';
}
.marquee span {
display: inline-block;
padding-left: 100%;
text-indent: 0;
animation: marquee linear infinite;
background-color: #000000;
color: white;
bottom: 0px;
}
/* Make it move */
#keyframes marquee {
0% {
transform: translate(10%, 0);
}
100% {
transform: translate(-100%, 0);
}
}
/* Make it pretty */
.scroll {
padding-left: 1.5em;
position: fixed;
font: 50px'Verdana';
bottom: 0px;
color: white;
left: 0px;
height: 10%;
}
</style>
The reason why your CSS doesn't work in Edge is because of the font declaration. There is a space missing. Change inside .marquee:
font: 50px Verdana;
The reason it doesn't work in IE10/IE11 is that the animationDuration property is not supported in JavaScript. See here
If you want to make it work though, you should remove the animation: marquee linear infite; from the css and add it to the JavaScript:
CSS
.marquee span {
display: inline-block;
padding-left: 100%;
text-indent: 0;
background-color: #000000;
color: white;
bottom: 0px;
}
JS
spanSelector[i].style.animation = "marquee linear infinite " + timeTaken + "s";
Now it should work in IE10/IE11 :)

Categories