在 pushState 之后 iOS8 Safari :nth-child() 选择器不起作用

Posted

技术标签:

【中文标题】在 pushState 之后 iOS8 Safari :nth-child() 选择器不起作用【英文标题】:iOS8 Safari after a pushState the :nth-child() selectors not works 【发布时间】:2014-11-19 20:50:24 【问题描述】:

编辑: 我向 Apple 报告了这个错误,现在它已关闭,在 beta ios 9.0 (13A4254v) 上进行了测试并且工作正常。

为更好的解释而编辑:

我在一个网页中有一堆文章,都包裹在一个 div(列)中。这些文章有一个具有绝对位置和固定宽度和高度的类。

有一个按钮可以应用: - 一个 translate3d 到包装器/列 - 一个 window.history.pushState

所有样式都正确应用于所有文章,但是当我按下按钮并在 pushState 之后,所有/某些 nth-child() 样式都没有正确应用(左、上和宽度)。如果我将 :nth-child() 更改为 :nth-of-type() 在 pushState 之后一切正常。

当 Safari 确定激活切换到阅读器模式的可能性时,该问题似乎是可见的,在按下点击按钮并影响 translate3d 元素(硬件加速)之后。

它在使用 iPad2、iPad3 视网膜和 4 的 Safari iOS8 上发生。它不会在使用 iPad mini 视网膜时发生。使用 iOS7 之前一切正常,但使用 iOS8 则不行。

代码:

<html>
<head>
    <meta name="viewport" content="initial-scale = 1.0, maximum-scale = 1.0, minimum-scale = 1.0, user-scalable = 1.0">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <style>
        body 
            position: relative;
            width: 100%;
            height: 100%;
            padding: 0;
            margin: 0;
            overflow: hidden;
        
        #column 
            -webkit-transition: 0.35s; transition: 0.35s;
            -webkit-transform: translate3d(0px, 0px, 0px);

            position: absolute;
            top: 10px;
            left: 10px;

            border: 1px solid Grey;
            width: 300px;
            height: 225px;
        
        .moveColumn 
            -webkit-transform: translate3d(200px, 0px, 0px) !important;
        

    article 
        position: absolute;
        overflow: hidden;
    
    article:nth-child(1) 
        left: 0;
        top: 0;
        width: 300px;
        height: 300px;
        background-color: Red;
    
    article:nth-child(2) 
        left: 0px;
        top: 305px;
        width: 605px;
        height: 300px;
        background-color: Blue;
    
    article:nth-child(3) 
        left: 305px;
        top: 0;
        width: 300px;
        height: 300px;
        background-color: Green;
    
    .button 
        position: absolute;
        left: 10px;
        top: 250px;
        background-color: Grey;
    

    </style>
    <script language="javascript">
        var veces = 0;
        function moveColumn() 
            var column = document.querySelector('#column');

            column.classList.toggle('moveColumn');

            var obj = ;
            obj.sectionId = "section";
            window.history.pushState(obj, "TITLE", "/?vp=" + veces);
            veces++;
        
    </script>
</head>
<body>
    <div id="column">
        <article>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In eu urna quam. Duis et pellentesque ipsum, vitae varius erat. Nullam fringilla libero id est aliquet gravida. Quisque efficitur, quam bibendum posuere auctor, turpis arcu pulvinar sapien, interdum iaculis purus metus id velit. In in lorem ac dolor feugiat luctus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi viverra velit sed massa viverra consequat id eu tortor. Ut scelerisque massa ut leo rutrum blandit.

            Maecenas sit amet facilisis nulla, nec convallis nunc. Ut gravida, erat eget eleifend viverra, elit lacus ultrices turpis, vitae molestie felis tellus ac eros. Integer semper vitae sapien sit amet placerat. Praesent in sodales massa. Aliquam erat volutpat. Etiam maximus massa a scelerisque cursus. Pellentesque facilisis enim nec diam viverra facilisis. Morbi non nibh nulla. Praesent erat urna, porta sit amet dui eu, porta pulvinar metus. Nam quam odio, laoreet in nisi in, porta efficitur purus. In fringilla magna ac accumsan commodo.</article>
        <article>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In eu urna quam. Duis et pellentesque ipsum, vitae varius erat. Nullam fringilla libero id est aliquet gravida. Quisque efficitur, quam bibendum posuere auctor, turpis arcu pulvinar sapien, interdum iaculis purus metus id velit. In in lorem ac dolor feugiat luctus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi viverra velit sed massa viverra consequat id eu tortor. Ut scelerisque massa ut leo rutrum blandit.

            Maecenas sit amet facilisis nulla, nec convallis nunc. Ut gravida, erat eget eleifend viverra, elit lacus ultrices turpis, vitae molestie felis tellus ac eros. Integer semper vitae sapien sit amet placerat. Praesent in sodales massa. Aliquam erat volutpat. Etiam maximus massa a scelerisque cursus. Pellentesque facilisis enim nec diam viverra facilisis. Morbi non nibh nulla. Praesent erat urna, porta sit amet dui eu, porta pulvinar metus. Nam quam odio, laoreet in nisi in, porta efficitur purus. In fringilla magna ac accumsan commodo.</article>
        <article>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In eu urna quam. Duis et pellentesque ipsum, vitae varius erat. Nullam fringilla libero id est aliquet gravida. Quisque efficitur, quam bibendum posuere auctor, turpis arcu pulvinar sapien, interdum iaculis purus metus id velit. In in lorem ac dolor feugiat luctus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi viverra velit sed massa viverra consequat id eu tortor. Ut scelerisque massa ut leo rutrum blandit.

            Maecenas sit amet facilisis nulla, nec convallis nunc. Ut gravida, erat eget eleifend viverra, elit lacus ultrices turpis, vitae molestie felis tellus ac eros. Integer semper vitae sapien sit amet placerat. Praesent in sodales massa. Aliquam erat volutpat. Etiam maximus massa a scelerisque cursus. Pellentesque facilisis enim nec diam viverra facilisis. Morbi non nibh nulla. Praesent erat urna, porta sit amet dui eu, porta pulvinar metus. Nam quam odio, laoreet in nisi in, porta efficitur purus. In fringilla magna ac accumsan commodo.</article>
    </div>

    <div class="button" onclick="javascript:moveColumn();"> Click me to move column</div>
</body>
</html>

你有过这样的经历吗?

【问题讨论】:

当 safari 确定激活切换到阅读器模式的可能性时,问题似乎很明显。我可以使用列出的相同代码在一个简单的 HTML 页面上重现该问题,但在文章中包含一些文本以让 safari 激活阅读器模式按钮。 【参考方案1】:

将新元素附加到列表时(例如,使用 AJAX):nth-child(2n+1) 似乎应用于每个新元素。

这只发生在运行 iOS8 的 32 位设备上(例如 iPhone5,但不是 iPhone 5s 或 6,甚至不是 iPhone5 Simulator)。

解决方案是在 Apple 解决此问题之前使用 :nth-of-type()

【讨论】:

【参考方案2】:

确实 nth-child 在 IOS8 上不起作用。

切换到nth-of-type 对我有用。

很好支持https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-of-type

也就是说,如果你不想冒险,你可以检测 IOS 8 如下。

function isIOS8() 
  if ("600.1.4" == $.browser.version || ~navigator.userAgent.indexOf('OS 8_') )
    return true;
  
  return false;


var i=0,
    $el = $('ul.poll');

if( isIOS8() )
    $el.find(' li:nth-of-type(' + (i + 1) + ')').text('my first Child');
else
    $el.find('.choice:nth-child(' + (i + 1) + ')').text('my first Child');

【讨论】:

这就是我采用的解决方案,但不方便的是 :nth-of-type() 的语义含义与 :nth-child() 不同。我将该错误注册到苹果。谢谢。 我同意关注点分离较少。必须在选择器中使用标记名对我来说并不理想。感谢您报告该错误。 嘿@josea 你有那个错误报告的链接吗? 可能只是我,但看起来 iOS 8.1.2 更新修复了这个问题? @Cub3 抱歉,我可以在 ipad mini ios8.1.2 上重现它【参考方案3】:

我遇到了类似的问题,我在这里添加它以防其他人看到,因为这是我发现的唯一一篇关于 iOS 8 和 CSS 选择器问题的帖子。

我的特殊问题是使用 nth-child 来选择由 Javascript 创建的元素,我们充分利用了 nth-child,它不再适用于 iOS 8。

nth-of-type 确实工作,正如his answer中的svas-s-r所述。

我创建了一个js sample(也是最后的代码),它显示了 iOS 8 和 document.querySelectAll 以及 nth-child css 选择器的问题。

根据here 的信息推测,尤其是下面的引用,我认为它们正在缓存或预处理选择器。

iOS 8 在各个方面也明显快于 iOS7,document.querySelectorAll 提高了 4 倍。

<style>
    .red  border: 1px solid red; 

    .green  border: 1px solid green; 

    tr.test > td:nth-child(n)  background-color: yellow; 
</style>

<table id='tbl'>
    <tr>
        <td>a1</td><td>2</td><td>3</td><td>4</td><td>5</td>
    </tr>
    <tr class='test'>
        <td>b1</td><td>2</td><td>3</td><td>4</td><td>5</td>
    </tr>
    <tr class='test'>
        <td>c1</td><td>2</td><td>3</td><td>4</td><td>5</td>
    </tr>
    <tr>
        <td>d1</td><td>2</td><td>3</td><td>4</td><td>5</td>
    </tr>
    <tr class='test'>
        <td>e1</td><td>2</td><td>3</td><td>4</td><td>5</td>
    </tr>
</table>

<script>
var row = $('<tr></tr>').addClass('test');

var cell1 = $('<td></td>').text('f1');
cell1.appendTo(row);

var cell2 = $('<td></td>').text('2');
cell2.appendTo(row);

var cell3 = $('<td></td>').text('3');
cell3.appendTo(row);

var cell4 = $('<td></td>').text('4');
cell4.appendTo(row);

var cell5 = $('<td></td>').text('5');
cell5.appendTo(row);

var tbl = $('#tbl');
row.appendTo(tbl);

var iRedCol = 3;
$('#tbl').find('tr.test > td:nth-child(' + iRedCol + ')').addClass('red');

var iGreenCol = 4;
$('#tbl').find('tr.test > td:nth-of-type(' + iGreenCol + ')').addClass('green');
</script>

【讨论】:

以上是关于在 pushState 之后 iOS8 Safari :nth-child() 选择器不起作用的主要内容,如果未能解决你的问题,请参考以下文章

App调用safar

iOS8之后搜索框的常规实例

使用 window.history.pushState 函数时无法在“历史”错误上执行“pushState”

iOS8之后,UITableViewRowAction实现滑动多个按钮

iOS开发小技巧--iOS8之后的cell自动计算高度

iOS 8 之后,还能继续使用 UIActionSheet 和 UIAlertView 吗?