您的位置:

Flow-root:优化CSS布局的最佳选择

一、什么是flow-root?

在CSS中,我们经常会遇到父元素高度无法被子元素撑起的情况。比如,我们想让父元素的背景色或边框覆盖在子元素上,但是父元素的高度由其子元素的高度决定,子元素内容变化时,父元素的高度无法自适应。在这种情况下,我们可以使用BFC(Block Formatting Context)来解决这个问题。而Flow-root是一种常用的创建BFC的方法。

Flow-root是容器元素的新属性。它为容器元素创建了一个新的BFC,可以隔离其子元素对外面的元素的影响。它最常用于解决margin垂直方向重叠(Margin collapsing)的问题,以及清除浮动造成的布局破碎等问题。在不需要使用clearfix类似的解决方案的情况下,可以使用Flow-root作为更简单的解决方案。


.box {
  display: flow-root;
}

二、Flow-root的特点

1、创建BFC

Flow-root可以为容器元素创建BFC,使得该元素成为一个独立的自包含块级格式化上下文。

举个例子,当我们需要在父元素上设置 overflow: hidden 以防止子元素浮动溢出时,可以使用 flow-root 代替 overflow: hidden。


.box {
  display: flow-root;
  /* overflow: hidden; */
}

2、隔离外部元素

Flow-root可以将一个容器元素的内容和子元素隔离开来,防止它们溢出父元素。

例如,一个包含浮动子元素的容器,在设置了 overflow: hidden 或者其他 BFC 规则之后,将会生成一个新的块级格式化上下文并阻止父元素大小的塌陷。

3、margin垂直方向重叠问题解决

Flow-root可以解决margin垂直方向重叠(Margin collapsing)问题。

Margin垂直方向重叠是指两个相邻元素的Margin垂直距离会缩小到一个较大的值。Flow-root会使包含盒子成为BFC,形成边界,从而防止外部Margin进入到包含块内部。

三、Flow-root的应用场景

1、解决float浮动造成的高度塌陷

在 float 浮动元素后面加上 clear 属性也可以解决高度塌陷问题,但是 clear 属性不如 Flow-root 方便和灵活,特别是在使用 :after 伪元素去清除浮动时缺点较为明显。


.box:after {
  content: "";
  display: table;
  clear: both;
}

.box {
  display: flow-root;
}

2、处理margin垂直方向重合问题

理论上,如果我们想要避免两个相邻元素的Margin重叠,可以使用 BFC 或 IFC 来解决。但是在实际应用中,在不清除浮动的情况下,要使用BFC或IFC来处理 margin 重合问题就需要花费额外的代码和功夫。使用flow-root这个CSS属性,解决margin垂直方向重叠问题将是易如反掌的事情。


.box {
  display: flow-root;
}

3、将子元素完全包裹

如果容器元素中的子元素使用了 float 或者绝对定位,容器元素的高度将无法自适应。在这种情况下我们可以使用flow-root来解决这个问题。


.box {
  display: flow-root;
}
.box-child {
  position: absolute;
  left: 0;
  top: 0;
}

四、Flow-root的浏览器兼容性

目前,Flow-root在大部分现代浏览器中的兼容性良好。IE 11 和 Edge 11 浏览器需要使用-ms-flow-into替代display: flow-root,不支持flow-root。

五、总结

Flow-root是一种比较新的属性,它可以轻松解决布局中经常出现的问题。它的使用场景主要包括解决float造成高度塌陷问题,处理margin垂直重叠问题,完全包裹子元素等。虽然IE 11和Edge 11不支持flow-root,但作为一种优化布局的CSS属性,Flow-root应该会在未来的布局中扮演着更加重要的角色。

Flow-root:优化CSS布局的最佳选择

2023-05-22
掌握最佳CSS布局技巧 - 优化网页设计的关键

2023-05-12
如何用 CSS 缩进优化代码布局?

2023-05-12
如何选择合适的CSS单位优化你的网站布局?

2023-05-12
前端学习笔记

2023-05-12
如何使用网格布局创建响应式布局

2023-05-16
使用CSS让图片向右对齐的最佳实践

2023-05-12
响应式布局实现网页适配

2023-05-14
CSS响应式布局

2023-05-12
CSS媒体查询优化网站视觉体验

2023-05-12
CSS字间距值的最佳选择

2023-05-12
如何优化CSS布局的display属性

2023-05-12
优化程序等待时间的最佳方式

2023-05-12
栅格化布局

2023-05-23
CSS Size优化:如何优化页面元素的尺寸

2023-05-12
如何优化页面布局和间距

2023-05-12
如何选择最适合您的CSS测量单位

2023-05-12
CSS负值优化页面布局

2023-05-12
深入探讨flex-flow属性

2023-05-20
when-present<#else>when-missing. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- ---- FTL stack trace ("~" means nesting-related): - Failed at: ${item.id} [in template "article/detail/index.ftl" at line 48, column 106] ---- Java stack trace (for programmers): ---- freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...] at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134) at freemarker.core.EvalUtil.coerceModelToTextualCommon(EvalUtil.java:481) at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:401) at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:370) at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:104) at freemarker.core.DollarVariable.accept(DollarVariable.java:63) at freemarker.core.Environment.visit(Environment.java:371) at freemarker.core.IteratorBlock$IterationContext.executedNestedContentForCollOrSeqListing(IteratorBlock.java:321) at freemarker.core.IteratorBlock$IterationContext.executeNestedContent(IteratorBlock.java:271) at freemarker.core.IteratorBlock$IterationContext.accept(IteratorBlock.java:244) at freemarker.core.Environment.visitIteratorBlock(Environment.java:645) at freemarker.core.IteratorBlock.acceptWithResult(IteratorBlock.java:108) at freemarker.core.IteratorBlock.accept(IteratorBlock.java:94) at freemarker.core.Environment.visit(Environment.java:335) at freemarker.core.Environment.visit(Environment.java:341) at freemarker.core.Environment.visit(Environment.java:341) at freemarker.core.Environment.process(Environment.java:314) at freemarker.template.Template.process(Template.java:383) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:332) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:266) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:220) at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:181) at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:314) at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1431) at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1167) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1106) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at com.software.filter.HttpSpiderIdentifyFilter.doFilter(HttpSpiderIdentifyFilter.java:51) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:340) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) at java.base/java.lang.VirtualThread.run(VirtualThread.java:309)