使用premailer处理嵌套媒体查询CSS时遇AttributeError报错求助
解决Premailer 3.10.0处理嵌套媒体查询的AttributeError问题
问题场景
尝试用premailer转换包含嵌套媒体查询的CSS代码:
<style type="text/css"> @media (prefers-color-scheme: dark) { .textPrimary { color: #E2E2E2 !important; } @media (max-width: 630px) { body, .footerContainer { background-color: #1E1E1E !important; } } } </style>
执行转换代码:
html = instance.transform(html, pretty_print=False)
触发错误:
File "/usr/local/lib/python3.10/dist-packages/premailer/premailer.py", line 414, in transform style.text = self._css_rules_to_string(these_leftover) File "/usr/local/lib/python3.10/dist-packages/premailer/premailer.py", line 683, in _css_rules_to_string for key in rule.style.keys(): AttributeError: 'CSSMediaRule' object has no attribute 'style'. Did you mean: '_type'?
使用premailer 3.10.0,测试过Python 3.8和3.10版本,问题未解决。
问题原因
Premailer 3.10.0的_css_rules_to_string方法未处理嵌套媒体查询的场景:该方法默认遍历的是普通样式规则(具备style属性),但嵌套的媒体查询属于CSSMediaRule对象,没有style属性,遍历过程中触发属性不存在的错误。
解决办法
1. 扁平化媒体查询(快速解决)
将嵌套的媒体查询拆分为并列的复合媒体查询,修改后的CSS如下:
<style type="text/css"> @media (prefers-color-scheme: dark) { .textPrimary { color: #E2E2E2 !important; } } @media (prefers-color-scheme: dark) and (max-width: 630px) { body, .footerContainer { background-color: #1E1E1E !important; } } </style>
这种结构符合Premailer的解析逻辑,不会触发错误。
2. 升级Premailer版本
Premailer后续版本(如4.x及以上)已修复嵌套媒体查询的处理缺陷,执行升级命令:
pip install --upgrade premailer
升级后重新测试转换流程,确认问题是否解决。
3. 预处理CSS(自定义方案)
若无法升级版本,可使用cssutils等工具预处理CSS,将嵌套媒体查询展开为并列结构后再传入Premailer处理。核心逻辑示例:
import cssutils # 解析原CSS样式 css_text = """ @media (prefers-color-scheme: dark) { .textPrimary { color: #E2E2E2 !important; } @media (max-width: 630px) { body, .footerContainer { background-color: #1E1E1E !important; } } } """ sheet = cssutils.parseString(css_text) # 自行实现遍历逻辑,将嵌套媒体查询合并为复合条件的并列规则 # 处理后的CSS再传入Premailer进行转换
内容的提问来源于stack exchange,提问作者Rijoanul Hasan Shanto
相关产品推荐
相关产品推荐

