JS启动优先于CSS

7

这个问题目前在Chrome中发生,但我在Firefox中没有遇到过这个问题(至少还没有)。

以下是一个非常简化的版本来描述我的问题。

HTML:

<div class="thumbnail">
  <a href='#' id="clickMe">Click me!</a>
</div>

CSS:

div {
    width: 200px;
    height: 300px;
    background-color: purple;
}
a {
    position: absolute;
}
@media (max-width: 991px) {
    div {
        height: 200px;
    }
}

Javascript:

$(document).ready(function () {
    var $parent = $('#clickMe').parent();
    function resize() {
        $('#clickMe').offset({
            top: $parent.offset().top + $parent.height()-$('#clickMe').height()
        });
    }
    $(window).on('resize', resize);
    resize();
});

问题:
那么当我调整大小时(不通过拖动),会发生什么?好吧,javascript首先启动并设置<a></a>的位置,然后如果我们小于992像素,CSS应用高度变化。
从逻辑上讲,按钮现在在div的外部可见,而不是像我最初定义的那样在边框上。
这篇文章中提出了一个临时解决方案。
链接:jQuery - 如何等待“调整大小”事件的“结束”,然后执行操作?
var doit;
    $(window).on('resize', function(){ clearTimeout(doit); doit = setTimeout(resize, 500); });

临时解决方案不是我要寻求的:

然而,在我的情况下,我并不一定需要在调整大小事件实际完成后才调用'resize'。 我只是希望我的 JavaScript 在 CSS 加载完成/或完成其更改后运行。 而且使用该函数“随机”运行 JS 可能会感觉非常缓慢,因为 CSS 可能已经完成。

问题:

是否有解决方法? 有人知道 JS 中的技术可以等待调整大小期间完全应用修改的 CSS 完成吗?

其他信息:

在 jsfiddle 中测试这个可能不会像我一样产生相同的结果。 我的 CSS 文件有很多行,并且我正在使用 Twitter Bootstrap。 这两个占用了很多资源,减慢了 CSS 的应用(我想,如果我错了,请告诉我)。

Miljan Puzović 提出了通过 JS 加载 CSS 文件的解决方案,然后在 CSS 结束时应用 JS 更改的事件。


2
CSS/JS是内联添加还是作为外部资源添加的?您是将其添加到“head”中还是在关闭“body”之前添加的? - Sergiu Paraschiv
1
尝试阅读这篇文章:https://dev59.com/53M_5IYBdhLWcg3wjj-r - Sergiu Paraschiv
2
这样怎么样:使用JS插入CSS,当事件完成后再插入/应用其他JS? - Miljan Puzović
1
我不是很理解这个问题。有人能为我澄清一下吗? - Muqito
1
编辑在实际问题陈述之前的顶部和明确添加而不是文本的一部分,对于新读者来说非常令人困惑(它让我感到困惑)。也许将它们编辑到问题中会更好? - Jeroen
显示剩余8条评论
7个回答

5

我认为这三个简单的步骤将实现预期的功能(请仔细阅读:我建议您阅读有关提及属性的更多信息以深入了解其工作方式):

  1. 响应式流体布局问题应始终首先(如果不是严格)使用CSS进行解决。

    因此,删除所有JavaScript代码。

  2. 你已经将内部a#clickMe元素的位置绝对定位。

    这意味着它将在最近的相对定位元素中定位。根据提供的样式,它将在body元素中定位,因为没有其他元素中的position: relative;(默认position值为static)。根据提供的脚本,它似乎应该在其直接父容器中定位。要这样做,请在div.thumbnail元素中添加position: relative;

  3. 根据您提供的脚本,似乎需要将a#clickMe放在div.thumbnail的底部。

    现在我们确定添加到a#clickMe的样式是相对于div.thumbnail,只需将bottom: 0px;添加到a#clickMe元素中,它就会相应地定位,独立于其父容器的高度。请注意,这将在调整窗口大小时自动重新排列(无需脚本)。

最终代码将如下所示(在此处查看fiddle):

JS:

 /* No script needed. */

CSS:

div {
    width: 200px;
    height: 300px;
    background-color: purple;
    position: relative; //added
}
a {
    position: absolute;
    bottom: 0px; //added
}
@media (max-width: 991px) {
    div {
        height: 200px;
    }
}

如果您仍然坚持使用媒体查询更改检测,请参考以下链接:

http://css-tricks.com/media-query-change-detection-in-javascript-through-css-animations/

http://css-tricks.com/enquire-js-media-query-callbacks-in-javascript/

http://tylergaw.com/articles/reacting-to-media-queries-in-javascript

http://davidwalsh.name/device-state-detection-css-media-queries-javascript

Twitter Bootstrap - 如何检测媒体查询开始

Bootstrap:响应式设计 - 当窗口从980px调整为979px时执行JS


我同意只用JavaScript或CSS来完成所有事情可能会更简单,但我仍然想知道如何等待CSS完成后再应用JS。 - kemicofa ghost

4

我喜欢你的临时解决方案(我之前也为类似的问题做过这样的事,我认为半秒对于用户来说不算太长,但也许对你的需求来说是太长了...)。

这里有一个替代方案,你很可能已经想到了,但我没有看到它被提到,那就是全部通过javascript实现,从你的css中删除@media (max-width....

function resize() {
    var width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
    if(width<992){
        $("div").each(function(e,obj){$(obj).height(200);});
    }
    $('#clickMe').offset({
        top: $parent.offset().top + $parent.height()-$('#clickMe').height()
    });

}

我喜欢尝试在CSS中做某些事情,如果我无法在CSS中完成,我就会用JS来实现。我认为最好的解决方案是要么全部使用CSS或JS。但我感觉将来还会遇到这个问题,所以我真的很想知道如何等待CSS应用更改的确切时刻。 - kemicofa ghost

2
您是否尝试将调整大小处理程序绑定到要侦听的对象,而不是窗口?

与其使用

$(window).on('resize', resize);

你可以尝试。
$("#clickMe").on('resize', resize);

Or maybe

$("#clickMe").parent().on('resize', resize);

2
在html页面中,在标签内放置到css文件的链接;接着,在标签之前放置到js文件的链接,看看会发生什么。这样做可以让css始终在js之前加载。希望这能对您有所帮助。

1
那是针对初始加载的。我说的是当所有内容都已经加载完毕并且发生调整大小事件时。 - kemicofa ghost

1

我同意falsarella的观点,你应该尝试只使用CSS来实现你想要做的事情。

无论如何,如果你想在应用CSS之后使用JS进行某些操作,我认为你可以使用requestAnimationFrame,但我无法测试它,因为我无法重现你所解释的行为。

来自MDN文档:

window.requestAnimationFrame()方法告诉浏览器您希望执行动画,并请求浏览器在下一次重绘之前调用指定的函数来更新动画。该方法以回调作为参数,在重绘之前调用。

我会尝试这样做:

var $parent = $('#clickMe').parent();

function resize(){

    $('#clickMe').offset({
        top: $parent.offset().top + $parent.height()-$('#clickMe').height()
    });
}


window.onresize = function(e){
    window.requestAnimationFrame(resize);
}

window.requestAnimationFrame(resize);

1
var didResize = false;
$(window).resize(function() {
    didResize = true;
});
setInterval(function() {
    if (didResize) {
        didResize = false;
        console.log('resize');
    }
}, 250);

这只检查 JavaScript 事件 resize 是否被调用并完成。我想要看到当一个 resize 的 CSS 修改完成时。 - kemicofa ghost

-1
有人知道一种等待 CSS 完全加载完成的技巧吗?
那么,$(window).load(function() { /* ... */ } 呢? (它只在页面完全加载后执行函数,因此在 CSS 加载后执行)

我应该让自己的表述更加清晰。我还想等待CSS修改在调整大小结束后真正完成。我尝试过加载,但只解决了部分问题。调整大小确实是令人沮丧的部分。 - kemicofa ghost

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