I don't know if what I want is possible with pure CSS, I'd prefer to avoid using JQuery because I'm building my app with ReacJS.
I have the following effect
.container {
display: flex;
flex-direction: column;
}
#box {
display: inline-block;
width: 100px;
height: 100px;
background-color: red;
transition: all 800ms ease-in;
position: relative;
right: calc(100px - 100%);
}
#chk:checked ~ #box{
right: 0;
}
<div class="container">
<label>check the input to see the effect</label>
<br/>
<input id="chk" type="checkbox">
<div id="box"></div>
</div>
It works when an input (checkbox) is checked, the thing is I want to reproduce the same effect but when an element is shown in the screen.
Why not to use JQuery?
As I'm building my app using ReactJS, using JQuery is not recommended neither the community nor Facebook.
I'd like to use CSS some React component, but I don't know how.
Check my own answer to see how I figured it out
Why don't you create a class instead of selector with checked property and then toggle the class with react.
Using CSS + ReactJS I solved doing this:
I used a checkbox to check or uncheck depending on where the scroll is. Then using CSS just change where the text is being rendered.
CSS Code:
#WhoIAm-title {
display: inline-block;
-webkit-transition: all 800ms ease-in;
-moz-transition: all 800ms ease-in;
transition: all 800ms ease-in;
position: relative;
right: -38%;
}
#WhoIAm-chk:checked ~ #WhoIAm-title {
right: 38%;
}
ReactJS Code:
componentDidMount() {
window.addEventListener('scroll', () => {
if (event.srcElement.body.scrollTop >= 620 && event.srcElement.body.scrollTop <= 650) {
this.setState({ checked: true });
}else if (event.srcElement.body.scrollTop >= 820 || event.srcElement.body.scrollTop <= 600) {
this.setState({ checked: false });
}
});
}
render() {
return (
<div id="whoiam" className="Container column">
<span>
<input type="checkbox" id="WhoIAm-chk" style={{ display: "none" }} checked={this.state.checked} />
<b id="WhoIAm-title">Title to toggle to right</b>
</span>
</div>
);
}
Related
I need to change width of the element on two different events and with different speeds. Can I somehow specify two transitions of the same property or do I have to change approach?
Let's say I want to quickly increase width of a box with hover. And be able to do the same thing with a button but slower. The problem here is when the class is removed from the box so is the 3s transition. I want a 3s transition to last for the shrinking of the box after the button is pushed again.
const box = document.getElementById("box");
function growQuickly(){
box.classList.toggle("grow");
}
.box{
height:100px;
width:100px;
background: red;
transition: .5s;
}
.box.grow{
width: 200px;
transition: 3s;
}
.box:hover{
width:200px;
}
<div class="box" id="box" ></div>
<button onclick="growQuickly()">GROW SLOWLY</button>
You can separate your logic into more classes and check if something is already included using js.
CSS
.box {
height: 100px;
width: 100px;
background: red;
transition-duration: 0.5s;
}
.box:hover {
width: 200px;
}
.wide {
width: 200px;
}
.slow {
transition-duration: 3s;
}
JS
const box = document.getElementById('box');
function growQuickly() {
const boxWidth = box.offsetWidth;
if (boxWidth === 200 && box.classList.contains('slow')) {
box.classList.toggle('wide');
setTimeout(() => box.classList.toggle('slow'), box.style.transitionDuration);
} else {
box.classList.toggle('wide');
box.classList.toggle('slow');
}
}
I have two divs that appear like this:
The idea is that when you close the bottom div (click on the 'X'), it should disappear.
And when you close the top div, it should disappear, and also the bottom div should slide up and take its place.
I'm very new to jQuery, but this is my first attempt:
function initAnnouncements() {
$(document)
// Closes announcement modules
.on('click', 'annoucements-close', function () {
$('announcement-div').hide();
})
}
#keyframes slideInFromRight {
0% {
transform: translateX(100%);
}
.1%{
opacity: 1;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
.announcements-container {
position: fixed;
top: 80px;
right: 20px;
z-index: 1001;
display: flex;
flex-direction: column;
width: 300px;
/* align-items: flex-end; */
}
.announcements-1 {
animation: slideInFromRight 0.4s ease;
opacity: 0;
animation-fill-mode: forwards;
}
.announcements-2 {
/* animation: 0.4s ease-out 0s 1 slideInFromRight; */
animation: slideInFromRight 0.4s ease;
opacity: 0;
animation-fill-mode: forwards;
animation-delay: .4s;
margin-top: 15px;
}
.annoucements-header {
background-color: #1481C3;
color: #ffffff;
font-family: "Proxima Nova Bold";
padding: 7px 10px;
}
.annoucements-close {
position: absolute;
right: 5px;
width: 24px;
height: 36px;
cursor: pointer;
opacity: .85;
}
.annoucements-close:hover {
opacity: 1;
}
.annoucements-close::before,
.annoucements-close::after {
content: '';
width: 24px;
height: 2px;
background: white;
position: absolute;
top: 7px;
left: 0;
}
.annoucements-close::before {
transform: rotate(-45deg);
}
.annoucements-close::after {
transform: rotate(45deg);
}
/*opened or closed*/
.announcement-div-opened {
display: none;
}
.announcement-div.opened .announcement-div-opened {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div class="announcements-container">
<div class="announcement-div announcements-1">
<div class="annoucements-header">
<span class="annoucement-type-quantity">2 School Announcements</span>
<i class="annoucements-close"></i>
</div>
</div>
<div class="announcement-div announcements-2">
<div class="annoucements-header">
<span class="annoucement-type-quantity">1 Admin Announcement</span>
<i class="annoucements-close"></i>
</div>
</div>
</div>
</body>
As you can see this isn't doing anything. I'm trying to toggle the class from 'open' (display:block) to 'closed' (display:none) when the annoucements-close <i> element is clicked on.
And ideally I would like for the second div to slide up when the top one is closed, but first I'd just like to get either one to disappear.
What's wrong with my code where that's not working as expected?
Link to JSFiddle
There are 2 issues with your code: the click() event is inside the function initAnnouncements that doesn't get called. You could move it outside of this function or call the function. Then you have issues with your selectors: It's
.on('click', '.annoucements-close', function () {
$('.announcement-div').hide();
})
instead of
.on('click', 'annoucements-close', function () {
$('announcement-div').hide();
})
for class selectors. Working Fiddle.
If you just want to hide the annoucement which was clicked upon, just change it to
.on('click', '.annoucements-close', function () {
$(this).closest('.announcement-div').hide();
})
I looked at your code and adjusted it a little to demonstrate:
Added your common class on the two announcements "announcement-div"
Attached the document click handler with the jQuery ready event
Used the delegated event selector to listen to clicks within the document that match that common selector
On click of one of the announcement-div's animate the height to 0 and then remove the element
Comments are included in the fiddle. Hope this is helpful!
// Fire this function when the document is ready
$(function() {
// Listen on the whole document for click events on the .announcement-div element
$(document).on('click', '.annoucements-close', function () {
// From the close button find the closest parent "announcement-div"
var annoucement = $(this).closest('.announcement-div');
// Function to run after animating the element (use .hide() to keep element but display:none)
function destroy() {
annoucement.remove();
}
// Animate the annoucement's height to 0 over 400ms and then call the destroy function
annoucement.animate({ height: "0px" }, 400, destroy);
});
});
Updated JS Fiddle
The problem I'm facing is:
I have a animated text which goes from right to left, this text change depending on the languague set, what is causing that the total width of the text changes too.
In this picture, the effect I want is working fine, because some properties are fixed.
Now, when I change for a longer text the problem cames up.
So, this is what I have now:
And this is what I'd like to have:
Here is the code I'm using:
ReactJS Side:
constructor(props) {
super(props);
this.state = {
checked: false
}
}
componentDidMount() {
window.addEventListener('scroll', () => {
if (event.srcElement.body.scrollTop >= 1400) {
this.setState({ checked: true });
}
});
}
render() {
return (
<div>
... stuff
<span style={{ fontSize: "40px", color: this.state.theme.COLOR_3 }}>
<input type="checkbox" id="Resume-chk" style={{ display: "none" }} checked={this.state.checked} />
<b id="Resume-title">{this.state.languageSet.RESUME}</b>
</span>
... more stuff
<div>
);
}
CSS Side:
//This is the text
#Resume-title {
display: inline-block;
-webkit-transition: color 200ms ease-in;
-moz-transition: color 200ms ease-in;
transition: color 200ms ease-in;
-webkit-transition: right 500ms ease-in;
-moz-transition: right 500ms ease-in;
transition: right 500ms ease-in;
position: relative;
right: -40.5%;
}
//This is the text when the checkbox is checked
#Resume-chk:checked ~ #Resume-title {
right: 40.5%;
}
So, the question is: How to fix it? Or maybe there is some concept I'm missing and it is a little bit more than just fixing a bug.
Also I'm not sure if doing things like right: -40.5%; and right: 40.5%; is a good practice, but I cant find a way to animate property like float or align.
Of course, if there is a way to fix it, but also there is a way to do it even better, It is also welcome!!!
EDITED: here the fiddle containing the whole html section, copied from dev console
You need a combination of positioning with right and a transform.
This is an usual idea for centering an element, adapted to your request:
.container {
width: 300px;
background-color: lime;
margin: 10px;
position: relative;
}
.item {
display: inline-block;
position: relative;
right: -100%;
transform: translateX(-100%);
transition: right 1s, transform 1s;
}
.container:hover .item {
right: 0%;
transform: translateX(0%);
}
<div class="container">
<div class="item">Item</div>
</div>
<div class="container">
<div class="item">Item long</div>
</div><div class="container">
<div class="item">Item longer longer</div>
</div>
Using transform on two elements works fine in IE and Firefox but somehow "stutters" in Chrome.
I've captured the different behaviours with some gifs:
Firefox
IE
Chrome (notice how the right border "jumps" around")
Example on jsfiddle
Is it possible to fix this behaviour in Chrome? I couldn't find anything when I searched.
Thanks for your help in advance :)
Here is some exemplary code.
HTML:
<div class="outer">
<div class="menu">
asdf
</div>
<div class="content">
<button id="trigger">toggle menu</button>
</div>
</div>
CSS:
.outer > div {
transition: transform 500ms ease, margin-right 500ms ease;
}
.menu {
background-color: #1d1f20;
top: 0;
left: -200px;
width: 200px;
position: fixed;
transform: translate(200px,0);
}
.content {
transform: translate(200px, 0px);
margin-right: 200px;
background: green;
}
JS:
var current = '200px';
$('#trigger').on('click', function() {
current = current === '200px' ? '0' : '200px';
$('.menu').css({transform: 'translate('+current+', 0)'});
$('.content').css({transform: 'translate('+current+', 0)', marginRight: current === '200px' ? '200px' : '0'});
});
I have a page that creates a pop-up notification whenever a message is broadcasted from another user. The pop-up is basically a div that holds content from the sent message with a button that allows you to close it.
Now I've researched a million ways to create transitions that extend properties using pseudo classes but my question is this: Is it possible to create a banner at the top of the page that slides down with the message when it's sent by another using pure CSS3 / transition mixins?
My thought was to transition the max-height property but obviously it isn't working. I'm assuming because there is no height to begin with.
CSS:
.banner-messages {
> div {
background-color: #74bce7;
color: #fff;
top: 0;
left: 0;
padding: 20px 30px;
position: relative;
line-height: 100%;
width: 100%;
max-height: 0;
z-index: 1000;
overflow-y: hidden;
#include drop-down;
}
}
#mixin drop-down {
max-height: 200px;
-webkit-transition: all 1.5s linear;
-moz-transition: all 1.5s linear;
-o-transition: all 1.5s linear;
transition: all 1.5s linear;
}
HTML:
<div id="test" class="banner-messages" data-bind="foreach: messages">
<div class="banner-message">
<img data-bind="imgSrc: 'radio.svg'">
<div class="banner-body">
<p class="banner-title">{{title}}</p>
<pre>{{message}}</pre>
</div>
<span class="exit-dialout-panel icon icon-closes" data-bind="visible: dismissable, click: $parent.dismissMessage.bind($parent, $data)"></span>
</div>
Try adding a class with the css binding that applies transform: translateY:
var Viewmodel = function Viewmodel() {
var that = this;
this.messages = ko.observableArray([]);
this.removeMessages = function removeMessages() {
that.messages.removeAll();
};
this.addMessage = function addMessage() {
that.messages.push("A new message came in");
};
};
ko.applyBindings( new Viewmodel() );
header {
transition: transform 0.3s;
transform: translateY(-110%);
background-color: lightblue;
padding: 2rem;
font-family: sans-serif;
}
header.active {
transform: translateY(0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<main>
<header data-bind="css: { active: messages().length > 0 }">
<ul data-bind="foreach: messages">
<li data-bind="text: $data"></li>
</ul>
<button data-bind="click: removeMessages">mark all as read</button>
</header>
</main>
<button data-bind="click: addMessage">Add message</button>