After a row is deleted from a table, its width may change. However, the table's width transition does not fire, probably because the width css property was never changed directly, only its calculated value.
How do I make a table smoothly animate its width after a row is deleted, even if its css style width has not changed?
Example:
<style>
table {
transition: all 500ms ease-in-out;
}
</style>
<script>
function test(button) {
var el=document.getElementById("to-delete");
el.parentNode.removeChild(el);
button.parentNode.removeChild(button);
}
</script>
<table>
<tr><td>id</td><td>type</td></tr>
<tr id="to-delete"><td>165495</td><td>user</td></tr>
<tr><td>12</td><td>user</td></tr>
</table>
<button onclick="test(this)">Test</test>
The same moment the row is deleted, the table width abruptly changes its width to the final value, despite the css transition:
table {
transition: all 500ms ease-in-out;
}
Is there any way to make the table obey the rule in this case?
It sounds like you want to animate the width of every column, and the height of the deleted row, to get a smooth effect all-around. CSS doesn't have an explicit command for this purpose, but it does have...
Animating the font size
If you can just get all the contents of the row to shrink away smoothly, then the browser's regular table handling will do what you're looking for.
<style>
td {
transition: font-size 500ms ease-in-out, padding 500ms ease-in-out;
}
.deleting > td {
font-size: 0;
padding: 0;
border-width: 0;
color: transparent;
}
</style>
<script>
function test(button) {
var el=document.getElementById("to-delete");
el.className = "deleting";
window.setTimeout(function() {
el.parentNode.removeChild(el);
}, 1000);
button.parentNode.removeChild(button);
}
</script>
<table>
<tr><td>id</td><td>type</td></tr>
<tr id="to-delete"><td>165495</td><td>user</td></tr>
<tr><td>12</td><td>user</td></tr>
</table>
<button onclick="test(this)">Test</test>
For the simple example in the question, animating the font size gets very close, and animating the padding gets the rest of the way. If you have more complex contents in your table cells (that aren't sized entirely in terms of ems), you may have to do something more complicated, such as replacing the contents with a div of the same size and then shrinking that div to nothing via the height/width properties.
Related
there is an example with content dropdown: https://codesandbox.io/s/expand-content-4pc09c?fil...
But the appearance of content on the button is quite fast. I need to set smoothness using the transition property, but it didn't work.
As far as I understand, you need to add some kind of appearance effect with the help of visability, but here there is a link to useState also tried to set a property for the content: transition: all 0.5s ease-out; but the animation is not happening
I also tried change styles like that:
const styles = {
height: expand ? "auto" : "0px",
maxHeight: expand ? "auto" : "0px",
overflow: expand ? "visible" : "hidden"
};
but it turns out that i have the same result
You have to keep on mind various things to make it works. In your codepen there's a typo in visibility animation in styles.css. I attached you a working snippet but I'm explaining you some important topics about how it works.
Explanation
First of all if you're toggling styles with you styles variable it'll no respect transition as it will be rendered as inline styles, so the approach I use was create a new .wrapper__content.expanded class and the class is the one that'll be toggled with the state.
Second about CSS properties:
visibility cannot be transitioned as it doesn't have 'in-between' values, when the time of the transition (let's suppose 300ms) had passed it will change to visible or hidden with no intermediate values, that's why it cannot be 'animated'. But if you still want to add this property for accessibility purposes you can add a transition-delay to this property timing to trigger the change when height transition had finish.
height property is a difficult one to animate because it needs explicit values to work and I recommend you not to change the height: auto that comes by default, as it'll be adapting to its content (avoiding overflow issues). Instead of transitioning this property you should use max-height in collapsed state with a value of 0 and in expanded state with a value that your content will never reach (1000px in my snippet). This will do the trick, don't forget to add overflow:hidden; to hide the content when it's collapsed.
I think this answer will fulfill you requirements, but any questions feel free to ask. Hope it helps.
const App =() => {
const [expand, setExpand] = React.useState(false);
const onToggle = () => {
setExpand(!expand);
};
return (
<div className="wrapper">
<div className="wrapper__expand">
<button onClick={onToggle} className="wrapper__expand-btn">
+
</button>
Expand
</div>
<div className={expand ? 'wrapper__content expanded' : 'wrapper__content'}>
expanded content
</div>
</div>
);
}
ReactDOM.render( < App / > , document.getElementById("root"));
.App {
font-family: sans-serif;
text-align: center;
}
.wrapper {
display: flex;
flex-direction: column;
}
.wrapper__expand {
display: flex;
column-gap: 10px;
}
.wrapper__content {
margin-top: 10px;
overflow: hidden;
max-height: 0;
transition: max-height .5s ease-in-out;
}
.wrapper__content.expanded {
max-height: 1000px;
}
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="root"></div>
We can really check transition using height property and somehow control the distance like that
transition: max-height .5s ease-in-out;
Сomment below solves my problem
Is it possible to transition css on what the computed style becomes, not what that style is explicity set to?
Example
I have the following CSS/HTML
.grow {
transition: height 1s ease-in-out;
}
.hidden {
display: none;
}
<ul>
<li>
<div class="grow">
<ul class="hidden">...</ul>
</div>
</li>
</ul>
Then if I use javascript to remove the hidden class the div will logically grow to fit the newly displayed content, however since the height property did not change, the transition does not take effect. Is there a way to overcome this behavior? If it is possible, I'd like to keep the solution to css.
You are talking about two different CSS properties: height and display. Your transition only applies to height property and, even with display: none; the element keeps the same height.
What you can do, actually, is something like this:
setTimeout(function() {
document.getElementById("hid").className = "";
}, 1000);
.grow div {
transition: height 3s ease-in-out;
display: block;
height: 20px;
overflow: hidden;
}
.grow .hidden {
height: 0;
}
<ul>
<li>
<div class="grow">
<div class="hidden" id="hid">.AaA..</div>
</div>
</li>
</ul>
Hope it helps you.
As Rolyataylor2 mentioned, you cannot animate automatic dimensions. I've encounted this problem before and have a relatively simple JS-based solution.
Check out this Codepen. It uses a small jQuery plugin that I wrote to set the height of the variable-height container to its calculated height based on the heights of its children. It actually clones the element, measures the height, destroys the clone, and explicitly sets the calculated height on the original element.
This is the full code for the plugin and here's the Gist. It's written in Coffeescript but I can convert it to JS if needed. Cheers!
$.fn.extend
setContentHeight: ->
return #each ->
$(#).css('height', $(#).getContentHeight())
getContentHeight: ->
elem = $(#).clone().css(
"height":"auto"
"display":"block"
).appendTo($(#).parent())
height = elem.css("height")
elem.remove()
return height
I have this div
<div id="view_album">
View Photo
</div>
And a css
#view_album {
text-align: right;
width: auto;
display: inline-block;
background: #005cb9;
color: white;
box-sizing: border-box;
padding: 10px;
-webkit-transition: all .5s ease-in-out;
-moz-transition: all .5s ease-in-out;
-o-transition: all .5s ease-in-out;
-ms-transition: all .5s ease-in-out;
transition: all .5s ease-in-out;
}
#view_album:hover {
width: 100%;
}
Is it possible to animate the width from auto to something? A final width of 100% isn't working but if I set the initial width to a specific value like 100px and so, it works. But I need it auto since the text inside the div, 'View Photo', can be other text, too like something longer than that.
On this site I'm working on:
As you can see, that div with 'View Album' has a specific width of 115px. Then animate to 100%. But if I change the text inside like, 'Abc', which is obviously shorter than View Album and does not need a 115px of width.
That's why I need it auto.
First, change ids to classes, since you are repeating same id for all album covers.
You can use auto width and after site is loaded, run jQuery script and add current width to css:
$(document).ready(function(){
$.each($('.view_album'), function(){
$(this).css('width', $(this).width() + 'px');
}
});
I don't think CSS can animate/do transitioning in the way you want. You have to use script to set the initial width explicitly. However we have to know the width which is calculated by the browser (from the style width:auto after the element is rendered), this can be done easily using getComputedStyle or simply by the css method in jQuery. The important thing here is you have to modify the style via the CSSRule, not via the style property of the element. I'm not sure why it is but looks like that's how CSS works. Here is the script to find the rule #view_album and set the width to a specific value so that the hovering can make it transition well:
var ss = document.styleSheets;
for(var i = 0; i < ss.length; i++){
var rules = ss[i].cssRules || ss[i].rules;
var br = false;
for(var j = 0; j < rules.length; j++) {
if(rules[j].selectorText == '#view_album'){
rules[j].style.width = $('#view_album').css('width');
br = true;
break;
}
}
if(br) break;
}
Demo.
NOTE: Doing so won't set the width:auto on your element any more, so you should not change the text of that element dynamically (I think this is not your use case). If you have to change it dynamically and the width should expand/collapse automatically, you can try setting width:auto on it first before setting the text/innerHTML.
Here is Another version allowing you to change the font-size of the #view_album so that the width is adjusted accordingly.
I'm trying to fade a Modal in when it's clicked, and have the experience be smooth on mobile devices.
I'm setting both opacity to 0 and display to none. Setting opacity alone isn't enough, as it makes the area underneath unclickable.
#Modal {
display: none;
opacity: 0;
transition: opacity 500ms ease 0s;
}
Fade in Code:
$('#Modal').show();
$('#Modal').css('opacity','100');
However, the Modal doesn't fade in, it simply pops into existence.
Setting a setTimeout here works, but who wants a click delay for the fade in?
What's the best way to fade an element in with an opacity transition without chaining together massive properties like z-index, or some such nonsense?
Toogling display property it's bad way for fade element, Similar topics were already processed e.g: CSS3 transition doesn't work with display property
"display:none; removes a block from the page as if it were never there. A block cannot be partially displayed; it’s either there or it’s not. The same is true for visibility; you can’t expect a block to be half hidden which, by definition, would be visible! Fortunately, you can use opacity for fading effects instead."
quotation author:
Hashem Qolami
You should try to do this by deelay like here Animating from “display: block” to “display: none”
or try toogling class like here: http://jsfiddle.net/eJsZx/19/
CSS:
.Modal {
display: block;
opacity: 0;
transition: all 300ms ease 0s;
height: 0px;
overflow: hidden;
}
.ModalVisible {
display: block;
opacity: 1;
height: 50px;
}
Jquery:
$('button').on('click', function () {
$('#ModalId').addClass('ModalVisible');
});
Html:
<div id='ModalId' class="Modal" > content <br> content </div>
<button>show</button>
Why don't you use jQuery's $("selector").fadeIn() method?
The supposedly correct answer above implies that the OP is attempting a transition on display. They are not. Calling show() will set the display property to block. Then setting the opacity should theoretically trigger the transition from opacity:0.
A similar question has been answered here. To quote #WhoTheHellIsThat, the reason the transition is not triggered is...
...because of the way styles are figured out. Style changes are
expensive so they are effectively saved up until they are needed (a
recalc check like .offsetHeight is called or the next frame needs to
be drawn).
However the answer code in that question was Vanilla Javascript, and I couldn't make it work in jQuery. I found another answer that solved it in jQuery, using a class to trigger the transition.
Here is the full CSS...
#Modal {
display: none;
opacity: 0;
transition: opacity 500ms ease 0s;
}
#Modal.fade-in {
opacity: 1;
}
And here is the full JS:
$('#Modal').show(0, function() {
$(this).addClass('fade-in');
});
Here is a fiddle from RoryMcRossan's answer, demonstrating the solution.
I'm trying to make a roster of member photos. When a user hovers over an image, information slides out from the image or fades into view with a description and links. The roster will change frequently and the members' order may need to be adjusted by a script that calculates their score.
The part of the puzzle I'm working on now is the reveal. With help, I can now make the contents appear, but the the CSS transition is weird and awkward. What is the recommended approach to constructing such an info pane? Using z-index, perphas?
CSS
*{
-webkit-transition: all 2s ease-in-out;
-moz-transition: all 2s ease-in-out;
-o-transition: all 2s ease-in-out;
transition: all 2s ease-in-out;
}
.dude>:first-child{
width:0px;
height:0px;
float:left;
visibility:hidden;
}
.dude:hover > :first-child {
width: auto;
height: auto;
visibility:visible;
float:none;
}
HTML
<table>
<thead><h4>Roster</h4></thead>
<tbody>
<tr>
<td><div class="dude"><div>THIS INFORMATION WILL APPEAR LIKE MAGIC</div><img alt="Scott" src="madeupphotoname.jpg" /><b>Scott</b></td>
<td><div class="dude"><div>THIS INFORMATION WILL APPEAR LIKE MAGIC</div><img alt="Sally" src="madeupphotoname2.jpg" /><b>Sally</b></td>
</tr>
</tbody>
</table>
Your patience and talent is appreciated. For any so interested, here is the jsfiddle of my project.
There are many ways to handle this.
This FIDDLE will show you one way
Each td contains an image and two divs. The one containing text is "hidden" and is only read when you hover over the holderdiv.
The text is moved to a div below the title, but it could be put anywhere, such as a slider, a popup, a bubble, etc...as you see fit.
I agree with Paulie_D's comments - but as a "first-cut", a table is OK.
JS
$('.holderdiv').mouseover(function(){
$('.showme').html( $( this ).text() );
});
$('.holderdiv').mouseout (function(){
$('.showme').html( '' );
});
jsFiddle: http://jsfiddle.net/timspqr/fyXby/5/