I am trying to smooth out this custom animation.
See Working Animation Here.
The problem I am having is that when the city name revolves up and replaces the old one, the text-align center causes the h2 text to re-align center in one frame. I want to smooth out this transition so it eases into the align center instead of just jumping to it.
I hope that explanation helps. Here is my code.
HTML
<div class="coverage">
<h2>Kellin has service in <span class="flip"></span></h2>
<ul class="coverage_list">
<li>Larkspur</li>
<li>Castle Rock</li>
<li>Monument</li>
<li>Palmer Lake</li>
<li>Colorado Springs</li>
<li>Pueblo</li>
<li>Peyton</li>
<li>Falcon</li>
<li>Calhan</li>
<li>Franktown</li>
<li>Elizabeth</li>
<li>Elbert</li>
<li>Glenwood Springs</li>
<li>Rifle</li>
<li>Silt</li>
<li>El Jebel</li>
<li>Carbondale</li>
<li>New Castle</li>
<li>Parachute</li>
<li>Battlement</li>
</ul>
</div><!-- end .coverage -->
CSS
/* Coverage Banner */
.coverage{
border: 2px solid #333;
width: 100%;
}
.coverage ul.coverage_list{
display: none;
}
.coverage h2{
font-size: 2em;
font-weight: 700;
padding: 0px;
margin:0px;
overflow: hidden;
display: block;
text-align: center;
white-space: nowrap;
}
.coverage h2 .flip{
display: inline-block;
position: relative;
padding: 0px;
margin: 0px;
}
.coverage h2 .flip .current{
position: relative;
left:0;
display: inline-block;
text-align: left;
width: 100%;
padding: 0px;
margin: 0px;
}
.coverage h2 .flip .newcity{
position: absolute;
display: inline-block;
text-align: left;
white-space: nowrap;
left: 0;
padding: 0px;
margin: 0px;
}
JS / Jquery
var coverageVars = {
index : 1,
count : 0,
flipTime : 500
}
// .current = Current City, position relative
// .newcity = New City, position absolute;
$(document).ready(function(){
// Load First City Into H2 Display
var firstCity = $('ul.coverage_list li:nth-child(1)').html();
$('.coverage h2 .flip').append('<span class="current">'+firstCity+'!</span>');
// Get Count
coverageVars.count = $('ul.coverage_list').children('li').length;
var flipTimer = setInterval(function(){
// Increase Counter
if( coverageVars.index < coverageVars.count ){
coverageVars.index += 1;
} else {
coverageVars.index = 1;
}
// Get City Names
var currentCity = $('.coverage h2 .flip .current').html();
var newCity = $('ul.coverage_list li:nth-child('+coverageVars.index+')').html();
// Append newcity span to flip element
$('.coverage h2 .flip').append('<span class="newcity" style="top:50px;">'+newCity+'!</span>');
$('.coverage h2 .flip .current').animate({top:'-50px'}, coverageVars.flipTime, function(){
$(this).remove();
});
$('.coverage h2 .flip .newcity').animate({top:0}, coverageVars.flipTime, function(){
console.log('done!');
$(this).removeClass('newcity').addClass('current');
});
}, 1500);
});
I figure i would have to align with margins and then put a css transition on the margins but I can't figure it out. Thanks for the help.
An other idea:
Get the width of your <h2> (without .flip)
Get the width of the next <li> that will be appended. For this .coverage_list can't be set to display: none, but you can set the height: 0 and overflow to hidden.
Animate your <h2> to the new width (<h2> + <li>). Maybe with 1-2px more, due to browser rendering
Repeat steps #2 and #3 and always animate the width before appending
Related
CSS:
After clicking the button, you will see the divs getting created in line. I want "divs" of second row to be arranged right below first row of "divs" but they getting arranged leaving a gap. The text alignments inside the "divs" shouldn't get disturbed.
function myFunction() {
addWordToList("Apple", "Fruit");
}
var spno = 0;
function addWordToList(Word, Meaning)
{
spno++;
var dv = document.createElement("DIV");
document.body.appendChild(dv);
dv.setAttribute("class", "tooltip");
dv.setAttribute("id", "pilldiv"+spno);
document.getElementById("pilldiv"+spno).textContent=Word;
dv.insertAdjacentHTML('afterend', " ");
var spn = document.createElement("SPAN");
dv.appendChild(spn);
spn.setAttribute("class", "tooltiptext");
spn.setAttribute("id", "spn"+spno);
document.getElementById("spn"+spno).textContent=Meaning;
}
.tooltip {
position: relative;
display: inline-block;
width: auto;
height: 1.6em;
margin: 4em auto;
padding-left: 10px;
padding-right: 10px;
border-radius: 10%/50%;
background: linear-gradient(to right, #11998E , #38EF7D);
font-weight: 700;
}
.tooltip .tooltiptext {
visibility: hidden;
}
.tooltip:hover .tooltiptext {
visibility: visible;
}
<!DOCTYPE html>
<html>
<head></head>
<body>
<button onclick="myFunction()">Click to Create Divs</button>
</body>
</html>
Change the tooltip's css to following:
.tooltip {
position: relative;
display: inline-block;
width: auto;
height: 1.6em;
padding-left: 10px;
padding-right: 10px;
border-radius: 10%/50%;
background: linear-gradient(to right, #11998E , #38EF7D);
font-weight: 700;
}
i.e. remove "margin: 4em auto;". Due to margin, the actual height of the box is getting increased and creating the gap.
The project:
I made a 3 items slider just using CSS and JS. I'm trying to adjust the proportion of one item to make sliding based on this proportion.
The problem:
the proportion isn't fixed and there is a slight space from the left side of all items and between items themselves. It seems they have borders that take a tiny space. and that space also affects sliding itself. I don't know if it's a CSS or JS problem!
Source Code on Codepen
HTML
<div id="slider">
<div class="SlideContainer">
<div class="img">
<img src="https://www.nicepng.com/png/detail/11-112605_punk-cat-berkley-cats-illustrations.png">
</div>
<h1 style="text-align:center;">1</h1>
</div>
<div class="SlideContainer">
<div class="img">
<img src="https://i.pinimg.com/736x/84/78/b9/8478b93283dc6eac074d437097a9fe74.jpg">
</div>
<h1 style="text-align:center;">2</h1>
</div>
...... etc
</div>
CSS
#slider {
height: 500px;
margin: 0;
padding: 0 .5%;
overflow: hidden;
white-space: nowrap;
scroll-behavior: smooth;
}
.SlideContainer{
vertical-align: top;
background-color: purple;
color: white;
height: 99% ;
margin: .5% 0;
width: 33%;
display: inline-block;
}
.img {
overflow: hidden;
max-width:200px;
max-height:200px;
border-radius: 50%;
display: block;
margin: 10px auto 0 auto;
text-align: center;
}
.img img{
height: 200px;
width: 200px;
}
JS
var Container = document.getElementById("slider");
var unitWidth = (Container.offsetWidth/3);
var slidesNo = (document.getElementsByClassName("SlideContainer").length - 2);
var i = 0;
var positionInfo = Container.getBoundingClientRect();
var height = positionInfo.height;
var width = (positionInfo.width/3);
function SlideLoop(){
var interval = setInterval(function(){
Container.scrollTo((unitWidth * i), 0);
//Container.scrollBy(unitWidth, 0);
i++;
if(i == slidesNo) {
i = 0;
clearInterval(interval);SlideLoop();
}
}, 1500);
};
SlideLoop();
Your problem is with using white-space: nowrap; in the slider and display: inline-block; in the slider items.
Using such methods to display items is not recommended because it would cause strange unexpected behavior. I suggest you learn flexbox. This is a great and easy guide that will help you.
as for your problem, change those css elements like this and it should work propely:
#slider {
height: 500px;
margin: 0;
padding: 0 .5%;
overflow: hidden;
scroll-behavior: smooth;
display: flex; /* displays items horizontally */
}
.SlideContainer{
vertical-align: top;
background-color: purple;
color: white;
height: 99% ;
margin: .5% 0;
min-width:33%; /* force the minimum width of items */
}
I'm new in coding, so please be nice with me :)
I'm trying to show the hidden text on mouseover.
I would like a transion from right to left, but only where there is actually some hidden/ellipsised text ( I cannot know how long is it)
I'have something like this:
<div class="card">
<div class="text-box">
<h1> /*injected text*/ </h1>
</div>
</div>
css :
.text-box {
background-color: blue;
color:white;
}
h1 {
text-overflow: ellipsis;
overflow: hidden;
#include transition(left 4s linear);
overflow-x: hidden;
position: relative;
right: 0px;
}
.card:hover h1, .card:active h1 {
right:100px;
overflow: visible;
}
I need something similiar to the third, but only for ellipsised text
https://codepen.io/yurigor/pen/mAPkWP
thanks
Here's the code you only need from that codepen snippet
html
<div class="marquee bluebox">
<span><span>Hover over or touch me to see animated scrolling of this string. Fancy but buggy. May be still can be improved.</span></span>
</div>
css
.bluebox, .stuff {
box-sizing: border-box;
padding: 5px;
width: 300px;
border: 1px blue solid;
background-color: rgba(0, 0, 255, 0.4);
margin-bottom: 5px;
float: left;
}
.marquee {
white-space: nowrap;
overflow: hidden;
}
.marquee span {
display: inline-block;
width: 100%;
}
.marquee span span {
transition: left 4s linear;
position: relative;
overflow: hidden;
text-overflow: ellipsis;
left: 0px;
}
.marquee:active span, .marquee:hover span {
width: auto;
}
.marquee:active span span, .marquee:hover span span {
left: calc(300px - 15px - 100%);
}
here's a demo
https://jsbin.com/dukukid/edit?html,css,output
the css code with a minor modification to avoid transition when the text going back to initial position. although i highly recommend you learn SASS because it makes the code snippet shorter as you can see in your link.
/*this function take a DOM element as an input, test if this element have an overflow
and then apply ellipsis and transition to it if its the case*/
function transitionEllipsised(element, textToAdd){
/*get the jQuery collection of this element to use jQuery innerHeight and innerWidth
methods on it and add the text to it*/
var $element = $(element).text(textToAdd);
//if the text did overflow in the width or the height of the container apply ellipsis transition
if (element.scrollHeight > $element.innerHeight()
|| element.scrollWidth > $element.innerWidth()) {
var innerHtml = $element.html();
//add marquee class to the element it will hide the overflow
$element.addClass("marquee")
//wrap the element in the two spans that will create the transition effect
.html(`<span><span>${innerHtml}</span></span>`);
}
}
//this is an example to use the function transitionEllipsised
/*when user click on the button the text on the input will be added to the h1 element
and apply transition only if text overflow*/
$("button.add-text").click(function(){
var headerExample = document.querySelector("h1.header-example");
//get the text of the user input
var textToAdd = $("input.text-to-add").val();
transitionEllipsised(headerExample, textToAdd);
});
/*hide overflow*/
.marquee{
white-space:nowrap;
overflow: hidden;
}
/*the css that you need to do the transition effect*/
.marquee span{
display: inline-block;
width: 100%;
}
.marquee span span{
position: relative;
overflow: hidden;
text-overflow: ellipsis;
left: 0px;
}
.marquee:active span,
.marquee:hover span{
width: auto;
}
.marquee:active span span,
.marquee:hover span span{
transition: left 4s linear;
left: calc(300px - 15px - 100%);
}
/*header of the example*/
h1.header-example{
/*important to fix the width and height of the container. if the text is longer the 300px there will be an overflow*/
width: 300px;
height: 40px;
border: red solid 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<!-- this is an example to use the function transitionEllipsised -->
<p>add some text using the input. if the text is longer then the container there will be transition effect to show the overflow</p>
<input type="text" class="text-to-add"><button class="add-text">add text</button>
<h1 class="header-example"></h1>
I have a grid set up where the blocks are centre aligned, thus I've done this using display: inline block and set text-align: center to the container. BUT now the client wants variable heights on the blocks which now leaves big gaps in the grid as they're inline-block. Alternatively I could use float: left but this won't work as the blocks need to be centred. I have a codepen setup here: https://codepen.io/anon/pen/WOaeve
I usually use the isotope plugin for grids but there's no layout mode that'll allow for centre aligned blocks so I need a solution that'll allow for all the gaps in the grid to be filled AND for the blocks to be centred. Here's my CSS markup also:
.feed-grid {
position: relative;
display: block;
width: 100%;
height: auto;
text-align: center;
font-size: 0;
}
.feed-grid .grid-block {
display: inline-block;
vertical-align: top;
margin-left: 6px;
margin-right: 6px;
margin-bottom: 12px;
width: auto;
height: 255px;
}
.feed-grid .grid-block.large {
height: 522px;
}
.feed-grid .grid-block img {
position: relative;
display: block;
width: auto;
height: 255px;
}
.feed-grid .grid-block.large img {
height: 522px;
}
Any solutions to this would be greatly appreciated!
It may solve your problem. I have used float: left; in .child elements.
.container {background: green; overflow: hidden; text-align: center; padding: 15px;}
.center-element {float: none; background: yellow; overflow: hidden; width: auto; box-sizing: border-box; display: inline-block; padding: 5px; vertical-align: middle;}
.child {float: left; padding: 12px 24px; background-color: red;}
.child:not(:first-child) {margin-left: 5px;}
<div class="container">
<div class="center-element">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
What about a vertical middle alignement in the cases you have a smaller image than its "row" ?
Here is a CodePen
$(document).ready(function(){
var rowHeight = 0;
var rowHeights = [];
var rowCount = 0;
var offset = $(".grid-block").first().offset().top;
// Loop throught all images to get their heights.
$(".grid-block img").each(function(){
// If on the same row
if($(this).offset().top == offset){
// Find the biggest height
if($(this).height() > rowHeight){
rowHeight = $(this).height();
rowHeights[rowCount] = rowHeight;
}
// If the row is different.
}else{
// Get the new row offset.
offset = $(this).offset().top;
rowCount++;
rowHeight = $(this).height();
rowHeights.push(rowHeight);
}
// Set a custom attribute to apply the right margins.
$(this).attr("data-row",rowCount);
});
//Here you have the array of row heights in console.
console.log(JSON.stringify(rowHeights));
// Loop again to apply some margins.
$(".grid-block img").each(function(){
var thisRowHeight = rowHeights[parseInt($(this).data("row"))];
// Apply the margin if this image is smaller than the row height.
if( $(this).height() < thisRowHeight ){
var margin = (thisRowHeight - $(this).height() )/2;
$(this).css({"margin":margin+"px 0"});
}
});
});
It "measures" the row height to apply a margin to small images... Making them at the middle.
Check this jsFiddle.
The orange bar is serving as a progress bar where the value under the circle is how high the progress bar should be.
Any idea why the overflow:hidden; is beeing disregarded and how do one solve this problem? Oblviously nothing should go outside the circle.
Also is there a better solution for this?
Modified your fiddle a little bit. Here is the link
Modifications:
Changed .outerContainer css to display:block from display:table and addedmargin-top:30px to p css
Check if this works for you.
position: absolute and overflow: hidden don't appear to be playing nicely with display: table/table-cell. Removing the table stuff you had in there to vertically center the text fixes the problem. In Firefox, at least.
I think it's the browser thing...
This is the CSS3 version...
.progressBar {
display: block;
width: 100%;
height: 0;
position: absolute;
bottom: 0;
left: 0;
background: #ec6730;
transition: height 1s;
}
.innerContainer:hover > .progressBar {
height: 300px;
}
http://jsfiddle.net/ZyhgT/2/
It no longer flashing 'cause browser handle the job (not js loop animation...). But still it shows the edge on animation finish!!! This could be the browser things... Could be a bug...
This is not related to jQuery or any javascript. In fact, if you delete all your javascript and manipulate the height of your .progressBar using css on li:hover, you will notice the bug anyway.
It appears to be a browser issue as reported on: https://code.google.com/p/chromium/issues/detail?id=157218
As a workaround try adding an imperceptible css transform to the mask element:
.outerContainer {
-webkit-transform: rotate(0.000001deg);
}
You just need to change your .outerContainer class and it works just fine!
.outerContainer {
position: relative;
display: block;
height: 96px;
width: 96px;
overflow: hidden;
background: #fff;
border: 2px solid #fff;
-webkit-border-radius: 50px;
border-radius: 50px;
}
Put the level class inside the outerContainer div and style the span inside the level class to be relatively positioned. In the JavaScript, to calculate the level, divide by 10 instead of 100 for the perfect circular hover effect.
Here is a fiddle.
HTML
<div class="outerContainer">
<div class="innerContainer">
<p>Circle 3</p>
<span class="progressBar"></span>
</div>
<div class="level"><span>75</span>
</div>
</div>
CSS
body {
background: blue;
}
#circles {
text-align: center;
margin: 100px 0;
}
li {
display: inline-block;
margin: 0 10px;
position: relative;
}
.outerContainer {
position: relative;
display: block;
height: 96px;
width: 96px;
overflow: hidden;
background: #fff;
border: 2px solid #fff;
-webkit-border-radius: 50px;
border-radius: 50px;
}
.innerContainer {
display: table-cell;
vertical-align: middle;
width: 100%;
margin: 0 auto;
text-align: center;
}
p {
color: #000;
width: 96px;
position: relative;
z-index: 2;
}
.progressBar {
display: block;
width: 100%;
height: 0;
position: absolute;
bottom: 0;
left: 0;
background: #ec6730;
}
.level span{
position:relative;
}
JS
$(function() {
$("#circles li").hover(function(){
var thisElement = $(this);
var level = $(this).find(".level").text();
var elementHeight = $(this).find(".outerContainer").height();
level = (level/10)*elementHeight;
$(thisElement).find(".progressBar").stop().animate({
height: level
}, 300);
}, function() {
var thisElement = $(this);
$(".progressBar").stop().animate({
height: 0
}, 300);
});
});
display: table doesn't work that good with CSS positioning;
you should avoid using that, and find some other way to vertically center your labels.
If your circles have a known height, like your code seems to indicate (height:96px ecc), then just use a fixed top position for an absolutely positioned <p> element:
http://jsfiddle.net/ZyhgT/5/
Note that you don't even need jQuery for this, it is all achievable with just CSS3 (unless you are targeting old browsers)