【问题标题】:Safari ignore CSS :not() ruleSafari 忽略 CSS :not() 规则
【发布时间】:2020-03-19 03:35:18
【问题描述】:

我遇到了 Safari 13.0.5 (14608.5.12)

的问题

尝试修改一些WordPress Divi builder plugin 样式时,我遇到了一个意外问题,即无法应用否定规则,该规则会阻止插件在必要时在特定位置设置样式。

修改文件:

src/wordpress/wp-content/plugins/divi-builder/includes/builder/styles/frontend-builder-plugin-style.min.css

所以我来自这个:

#et-boc .et-l .hentry,
#et-boc .et-l a,
#et-boc .et-l a:active,
#et-boc .et-l blockquote,
#et-boc .et-l div:not(.woocommerce-message,.star-rating),
#et-boc .et-l em,
#et-boc .et-l form,
#et-boc .et-l h1,
#et-boc .et-l h2,
#et-boc .et-l h3,
#et-boc .et-l h4,
#et-boc .et-l h5,
#et-boc .et-l h6,
#et-boc .et-l hr,
#et-boc .et-l iframe,
#et-boc .et-l img,
#et-boc .et-l input,
#et-boc .et-l label,
#et-boc .et-l li,
#et-boc .et-l object,
#et-boc .et-l ol,
#et-boc .et-l p,
#et-boc .et-l span,
#et-boc .et-l strong,
#et-boc .et-l textarea,
#et-boc .et-l ul,
#et-boc .et-l video {background: 0 0;
    border: none;
    -moz-border-radius: 0;
    -webkit-border-radius: 0;
    border-radius: 0;
    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    box-shadow: none;
    color: inherit;
    letter-spacing: normal;
    margin: 0;
    outline: 0;
    padding: 0;
    text-align: inherit;
    text-shadow: inherit;
    -moz-transition: none;
    -o-transition: none;
    -webkit-transition: none;
    transition: none;
    vertical-align: baseline;
}

至此:

#et-boc .et-l *:not(.no-divi-styles) .hentry,
#et-boc .et-l *:not(.no-divi-styles) a,
#et-boc .et-l *:not(.no-divi-styles) a:active,
#et-boc .et-l *:not(.no-divi-styles) blockquote,
#et-boc .et-l *:not(.no-divi-styles) div:not(.woocommerce-message,.star-rating),
#et-boc .et-l *:not(.no-divi-styles) em,
#et-boc .et-l *:not(.no-divi-styles) form,
#et-boc .et-l *:not(.no-divi-styles) h1,
#et-boc .et-l *:not(.no-divi-styles) h2,
#et-boc .et-l *:not(.no-divi-styles) h3,
#et-boc .et-l *:not(.no-divi-styles) h4,
#et-boc .et-l *:not(.no-divi-styles) h5,
#et-boc .et-l *:not(.no-divi-styles) h6,
#et-boc .et-l *:not(.no-divi-styles) hr,
#et-boc .et-l *:not(.no-divi-styles) iframe,
#et-boc .et-l *:not(.no-divi-styles) img,
#et-boc .et-l *:not(.no-divi-styles) input,
#et-boc .et-l *:not(.no-divi-styles) label,
#et-boc .et-l *:not(.no-divi-styles) li,
#et-boc .et-l *:not(.no-divi-styles) object,
#et-boc .et-l *:not(.no-divi-styles) ol,
#et-boc .et-l *:not(.no-divi-styles) p,
#et-boc .et-l *:not(.no-divi-styles) span,
#et-boc .et-l *:not(.no-divi-styles) strong,
#et-boc .et-l *:not(.no-divi-styles) textarea,
#et-boc .et-l *:not(.no-divi-styles) ul,
#et-boc .et-l *:not(.no-divi-styles) video {background: 0 0;
    border: none;
    -moz-border-radius: 0;
    -webkit-border-radius: 0;
    border-radius: 0;
    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    box-shadow: none;
    color: inherit;
    letter-spacing: normal;
    margin: 0;
    outline: 0;
    padding: 0;
    text-align: inherit;
    text-shadow: inherit;
    -moz-transition: none;
    -o-transition: none;
    -webkit-transition: none;
    transition: none;
    vertical-align: baseline;
}

此解决方案适用于 Chrome、Firefox 等! ...除了 Safari =/

这个浏览器有什么问题?

【问题讨论】:

  • 这是一个非常有框架的问题!我希望这是常态,而不是例外。

标签: css wordpress safari


【解决方案1】:

您还不能对所有浏览器使用:not() 中的选择器列表,这就是为什么您在 Safari 中看不到这项工作的原因——整个选择器列表都被删除了。见MDN's reference

你需要把它分成两个:not()s:

...
#et-boc .et-l *:not(.no-divi-styles) div:not(.woocommerce-message):not(.star-rating),
...

【讨论】:

  • 注意到了。似乎插件开发人员使用了 :not(.selector1, selector2) 尚不支持的 CSS4 功能
  • 上面描述的例子看起来很麻烦,但不幸的是一个简单的规则*:not(.selector)不适用于Safari浏览器
【解决方案2】:

无论如何,最好避免在样式中使用如此复杂的代码,并且不要偶然发现浏览器错误。我没有设法找出为什么 Safari 会以这种方式运行,但是,对于 DIVI plug-in,这样的解决方案会使代码更加复杂。我相信在未来的版本中会修复这个错误。

但是我找到了另一个简单的解决方案:由于DIVI plugin 对放置在其中的任何代码都非常具有攻击性,因此一个简单的方法是将应用程序和落入流中的代码的必要部分放入 iframe 中将您需要的代码与第三方干扰完全隔离开来。

例如,您可以这样做:

interest.pug

extends index
block content
    .interest
        .container.container--content.interest__container
            script.
                function interestIframeOnLoad () {
                    var interestIframe = document.getElementById('interest__iframe')
                    interestIframe.contentWindow.postMessage({
                        selector: '#interest',
                        //...your_app_init_options_here
                    }, '*')
                }

            iframe(
                src='./interest__iframe.pug'
                class='interest__iframe'
                id='interest__iframe'
                frameborder='0'
                onload='javascript: interestIframeOnLoad()'
            )

interest__iframe.pug

doctype html
html(lang='en')
    head
        meta(charset='UTF-8')
        meta(name='viewport', content='width=device-width, initial-scale=1.0')
        title Interest inner app
        script(src='../../assets/js/interest.js')

    body
        #interest
        script.
            let appWasLaunched = false;
            const iframe = window.top.document.getElementById('interest__iframe');

            function launchApp(options) {
                window.app.interest(options);
            }

            window.addEventListener('message', e => {
                if (!appWasLaunched) {
                    appWasLaunched = true;
                    var data = e.data;
                    launchApp(data);
                }
            }, false);

interest.js

import Vue from 'vue'
import App from './App.vue'

export default function interest (options) {
    new Vue({
        data: options,
        render: (h) => h(App)
    }).$mount(options.selector);
}

window.app = window.app || {};
window.app.interest = interest;

上面的代码使用parsel bundler 因此,您可以在iframe src 属性中使用.pag 扩展名,您甚至可以在该iframe 中使用.scssES6,基本上就我而言,用DIVI plugin 解决了这个问题。我希望我的回答对某人有用

【讨论】: