FreeMarker模板部分CSS样式在FlyingSaucer生成的PDF中不生效求助
我之前也踩过FlyingSaucer处理CSS伪元素高度的坑,结合你的情况,给你几个亲测有效的排查和解决思路:
检查父元素的定位与高度设置
FlyingSaucer对绝对定位元素的百分比高度计算逻辑比现代浏览器严格得多。你的.someClass::before是绝对定位,它的高度百分比是相对于最近的非static定位父元素来计算的。所以首先要给.someClass添加相对定位,同时确保它有明确的高度或能继承到有效高度:.someClass { position: relative; /* 如果元素是行内/行内块,需设置为块级 */ display: block; /* 根据实际场景,可设置min-height或明确高度 */ min-height: 100%; }父元素没设
position: relative的话,伪元素会默认相对于html/body,但FlyingSaucer对这种跨层级的百分比高度支持很差。尝试用vh单位替代百分比
有时候FlyingSaucer对高度百分比的继承链处理有bug,换成视口高度单位vh可以绕过这个问题:.someClass::before { content:""; border-left: thin solid; height: 100vh; /* 替换height:100% */ position: absolute; }注意
vh在PDF中的表现可能和浏览器略有差异,你可以根据实际生成效果调整数值(比如95vh)。补全高度继承链
你已经设置了html, body { height:100% },但要确保.someClass的所有父容器都有高度设置,中间不能断链:html, body, .some-class-parent, .someClass { height: 100%; position: relative; /* 必要时添加 */ }FlyingSaucer的渲染引擎不支持“自动推导父元素高度”,必须每个层级都显式设置高度才能让百分比生效。
用实体元素替代伪元素
如果以上方法都无效,可能是FlyingSaucer对::before伪元素的高度计算支持有限。你可以把伪元素换成实际的DOM元素(比如<span class="vertical-line"></span>),在FreeMarker模板中随.someClass一起渲染,然后给这个实体元素设置样式:.vertical-line { border-left: thin solid; height: 100%; position: absolute; } .someClass:last-child .vertical-line { height: 10px; }这种实体元素的样式兼容性在FlyingSaucer中会好很多。
本质上,FlyingSaucer基于旧版WebKit内核,对CSS3特性的支持远不如现代浏览器,伪元素、百分比高度这类特性经常有兼容性问题,优先从定位和高度链入手排查,不行就退而求其次用实体元素替代。
内容的提问来源于stack exchange,提问作者user1433327

