CSS3过渡效果:将子元素动画化至100%宽度,父元素立即跳转至100%宽度

5
我正在试图创建一个删除按钮,一旦你点击它,就会展开显示删除选项,这样你就不会误删任何东西。问题是父容器会立即跳到完整大小,而我希望它逐渐增长。
当我为父容器设置固定像素宽度时,可以克服此问题,但问题在于我并不总是知道内容的宽度。因此,我使用百分比来使其动态化。
我真的不知道如何清楚地解释它,所以我制作了一个演示页面给你看:http://jsfiddle.net/cgHcP/ HTML:
<div class="right">
    <div style="background-color: #000; display: inline-block;">
        <div class="roll-button">
            <div class="icon">x</div>
            <div class="text">Remove</div>
        </div>
    </div>
    <div style="background-color: #000; display: inline-block;">
        <div class="roll-button">
            <div class="icon">x</div>
            <div class="text">Remove</div>
        </div>
    </div>
</div>

CSS(层叠样式表):
/* Roll Button */
div.roll-button {
    float: right;
    display: inline;
    position: relative;
    height: 24px;
    width: 24px;
    -webkit-box-shadow: 0 0 0 2px #fff;
    -webkit-border-radius: 12px;
    text-align: center;
    vertical-align: middle;
    background-color: #fff;
    overflow: hidden;
    -webkit-transition: width .5s ease-in-out;
    transition: width .5s ease-in-out;
}

div.roll-button .icon {
    left: 0;
    display: inline;
    position: absolute;
    font-size: 24px;
    width: 24px;
    height: 24px;
    background-color: #ff3e3e;
    -webkit-border-radius: 12px;
    -webkit-transition: all .5s ease-in-out;
    transition: all .5s ease-in-out;
    text-align: center;
    vertical-align: middle;
    color: #fff;
    line-height: .7;
}

div.roll-button .text {
    float: left;
    display: inline;
    position: relative;
    height: 24px;
    overflow: hidden;
    -webkit-transition: all .5s ease-in-out;
    transition: all .5s ease-in-out;
    vertical-align: middle;
    line-height: 24px;
    color: #ff3e3e;
    font-weight: 700;
    padding: 0 0 0 24px;
    font-size: 12px;
}

div.roll-button:hover .text {
    padding: 0 5px 0 29px;
}

div.roll-button:hover .icon {
    -webkit-transform: rotateZ(-180deg);
}

div.roll-button:hover {
    width: 100%;
}

.right {
    float: right;
    margin-right: 200px;
}

当您查看这个示例时,您会注意到当鼠标悬停在子元素上时,父容器(黑色)会跳到完整大小。即使子元素似乎逐渐增长,这种行为会在将多个项放置在一行中时(就像在示例中一样,也是我想要做的)引起麻烦。
我试图仅使用CSS制作此按钮,但这就是我卡住的地方。有人有建议可以通过纯CSS实现吗?

我现在看到它只在Chrome上对我有效。Safari不能正常工作。在Safari中,它会突出显示动画到100%宽度的问题。我能否从固定宽度动画到100%宽度或自动宽度?当我为宽度设置固定像素值时,问题似乎得到解决。有一个已更改为固定宽度(似乎工作正常)的版本,请参见此更新后的fiddle:http://jsfiddle.net/cgHcP/2/。问题是我不能使用固定宽度,因为内容是动态的,所以宽度应该是动态的。 - mrcrazylee
我刚想提一下 - 问题在于从像素(px)转换为百分比(%)宽度。 - dc5
我猜的没错。所以没有办法在不使用JavaScript的情况下让它工作吗?我可以始终使用JavaScript来计算内容的宽度并将父元素的宽度设置为固定像素。我只是希望不使用JavaScript就能实现它。我尝试过使用max-width属性进行动画处理,但这会导致宽度动画出现问题。如果max-width大于元素宽度,则会从开头开始动画元素。如果max-width是宽度的150%,则转换将在1/3后开始。谢谢您的回复! - mrcrazylee
2个回答

6
实现你想要的效果的技巧是在 .text 上使用 width:auto 并限制其 max-width。这是一个 新的可以工作的 jsFiddle
div.roll-button .text {
    width: auto;
    max-width:0px;
}

div.roll-button:hover .text {
    max-width:100px; /* set this to the maximum allowed value.. */
}

我明白你的意思。问题在于我不知道子元素(文本标签)有多宽。我本来希望能够在不使用JavaScript的情况下解决这个问题,但如果目前连这都很难解决,那似乎只能借助JavaScript来实现了。 - mrcrazylee
@mrcrazylee,我可能没有理解问题所在...在我的回答中的jsFiddle上,它不是正常工作吗? - Yotam Omer
你的代码很棒。因为它设置了固定像素。但问题是标签文本可能会不同。当我改变按钮文本的长度时,75px就不够用了。例如,看一下我的更新后的代码:http://jsfiddle.net/cgHcP/4/. 我不能设置固定像素,因为我不知道按钮文本的大小。正如我之前所说的,我可以使用JavaScript来计算内容的宽度,然后将其设置为父元素的宽度。我的目标是仅使用CSS来实现。我猜这确实不可能。 - mrcrazylee
我忘了在问题本身中提到这一点,我只把它作为注释添加了进去,我的失误! - mrcrazylee
感谢您更新的fiddle!我也尝试过那种方法,但我认为我是一个太过于完美主义者了。现在的问题是动画不完全流畅。我希望X的旋转能够与文本标签同时开始和停止。唯一的方法是使用过渡到宽度100%或自动以使过渡按照我想要的方式工作。至少在webkit提供支持之前是这样。我将采用jQuery / CSS3组合通过计算内容的宽度来设置实际像素的宽度。我会更新结果。 - mrcrazylee
请查看我的更新版fiddle,其中使用了jquery解决方案。如果没有使用javascript,这似乎是一件非常麻烦的事情(如果有可能的话)。非常感谢您的帮助,它引导我得出了这个结果。 - mrcrazylee

0

好的,似乎不使用JavaScript很麻烦, 所以我决定使用jQuery的方式。

我现在将宽度设置为实际像素,以绕过在大多数浏览器中从像素宽度到自动或百分比转换时仍然存在的问题。我通过创建一个带有overflow:hidden的包装元素,并总结子元素的宽度来实现。我使用这个总和来设置按钮的实际像素宽度

此外,我还添加了一个计时器,在预设时间内关闭按钮。我的想法是这个按钮可以不必显示删除对话框询问是否真的要删除内容。也许这个小技巧对其他人也有用。

查看我的最新小技巧final result.

HTML

<div class="roll-button">
    <div class="icon">x</div>
    <div class="label">Short Label</div>
</div>
<div class="roll-button">
    <div class="icon">x</div>
    <div class="label">This is a very long label</div>
</div>

CSS

body {
    background-color: #ff3e3e;
}

.roll-button {
    margin-right: 12px;
    float: right;
    display: inline-block;
    width: 24px;
    height: 24px;
    overflow: hidden;
    -webkit-transition: all .5s ease-in-out;
    -moz-transition: all .5s ease-in-out;
    -o-transition: all .5s ease-in-out;
    transition: all .5s ease-in-out;
    white-space: nowrap;
    -webkit-border-radius: 12px;
    -moz-border-radius: 12px;
    border-radius: 12px;
    background-color: rgba(255,255,255,1);
    -webkit-box-shadow: 0 0 0 2px rgba(255,255,255,1);
    -moz-box-shadow: 0 0 0 2px rgba(255,255,255,1);
    box-shadow: 0 0 0 2px rgba(255,255,255,1);
}

.roll-button  .icon {
    display: inline-block;
    -webkit-transition: all .5s ease-in-out;
    -moz-transition: all .5s ease-in-out;
    -o-transition: all .5s ease-in-out;
    transition: all .5s ease-in-out;
    width: 24px;
    height: 24px;
    background-color: #ff0000;
    -webkit-border-radius: 12px;
    -moz-border-radius: 12px;
    border-radius: 12px;
    -webkit-box-shadow: 0 0 0 2px rgba(255,255,255,1);
    -moz-box-shadow: 0 0 0 2px rgba(255,255,255,1);
    box-shadow: 0 0 0 2px rgba(255,255,255,1);
    text-align: center;
    vertical-align: middle;
}

.roll-button .label {
    display: inline-block;
    height: 24px;
    padding: 0 15px 0 5px;
}

.roll-button.open .icon {
    -webkit-transform: rotateZ(-180deg);
}

JavaScript/jQuery

$(function() {
    $('.roll-button').bind('click',function() {
        var iconWidth = $(this).find('.icon').outerWidth();
        var newWidth = 0;
        var timer = [];
        var $elm = $(this);
        $(this).children().each(function(){ newWidth += $(this).outerWidth(); });
        if(!$(this).hasClass('open')) {
            $(this).addClass('open').css({'width':newWidth+'px'});
            setTimeout(function() { 
                $elm.removeClass('open').css({'width':iconWidth+'px'});
            },5000);
        }
    });
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接