前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >关于float元素浮动后高度变化导致排列错位的问题

关于float元素浮动后高度变化导致排列错位的问题

原创
作者头像
喵喵侠
修改于 2024-11-26 01:24:20
修改于 2024-11-26 01:24:20
2003
举报
文章被收录于专栏:喵喵学前端喵喵学前端

目录

好文推荐:https://cloud.tencent.com/developer/article/2470497 这篇文章主要介绍了工作流的概念及在 Python 中的实现方法,包括虚拟环境搭建、VSCode 配置、基础工作流示例、多个事件的处理以及工作流可视化分析等内容。同时,作者还推荐了一篇关于构建加载状态与流畅交互的精妙艺术的文章,并在结尾介绍了自己的技术背景和对技术交流分享的热情。

前言

你好,我是喵喵侠。在现代Web布局中,flex和grid布局用到的会比较多,但我们仍然会遇到一些老旧项目,里面的前端UI框架,采用的还是float布局。在这种情况下,如果你对float布局不了解,就会在开发的过程中踩到坑。下面我来为你讲解,float元素高度变化后,是如何影响相邻元素的,以及如何解决这样的问题。

问题描述

首先假设有一个容器盒子,宽度是300px,高度是300px,它里面有9个div子元素,元素的宽高都是100px,都是float:left左浮动。

正常效果

根据这样的描述,我写了一个正常效果的demo如下:

代码语言:html
AI代码解释
复制
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>浮动布局示例</title>
<style>
  .container {
    width: 300px;
    height: 300px;
    border: 1px solid #ccc;
    position: relative;
  }
  .box {
    width: 100px;
    height: 100px;
    float: left;
    text-align: center;
    line-height: 100px;
  }
  .box1 { background-color: #ff9999; }
  .box2 { background-color: #ffcc99; }
  .box3 { background-color: #ffff99; }
  .box4 { background-color: #ccff99; }
  .box5 { background-color: #99ffcc; }
  .box6 { background-color: #99ccff; }
  .box7 { background-color: #cc99ff; }
  .box8 { background-color: #ff99cc; }
  .box9 { background-color: #cccccc; }
</style>
</head>
<body>

<div class="container">
  <div class="box box1">1</div>
  <div class="box box2">2</div>
  <div class="box box3">3</div>
  <div class="box box4">4</div>
  <div class="box box5">5</div
  <div class="box box6">6</div>
  <div class="box box7">7</div>
  <div class="box box8">8</div>
  <div class="box box9">9</div>
</div>

</body>
</html>

正常效果如下:

问题效果

如果我把其中一个子元素,比方说子元素1的高度,修改为150px。此时你会发现,原本的子元素4跑到了原本5的位置,5跑到了原本6的位置,以此类推。

问题代码如下:

代码语言:html
AI代码解释
复制
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>浮动布局示例</title>
<style>
  .container {
    width: 300px;
    height: 300px;
    border: 1px solid #ccc;
    position: relative;
  }
  .box {
    width: 100px;
    height: 100px;
    float: left;
    text-align: center;
    line-height: 100px;
  }
  .box1 { height:150px;background-color: #ff9999; }
  .box2 { background-color: #ffcc99; }
  .box3 { background-color: #ffff99; }
  .box4 { background-color: #ccff99; }
  .box5 { background-color: #99ffcc; }
  .box6 { background-color: #99ccff; }
  .box7 { background-color: #cc99ff; }
  .box8 { background-color: #ff99cc; }
  .box9 { background-color: #cccccc; }
</style>
</head>
<body>

<div class="container">
  <div class="box box1">1</div>
  <div class="box box2">2</div>
  <div class="box box3">3</div>
  <div class="box box4">4</div>
  <div class="box box5">5</div>
  <div class="box box6">6</div>
  <div class="box box7">7</div>
  <div class="box box8">8</div>
  <div class="box box9">9</div>
</div>

</body>
</html>

问题效果如下:

解决方案

这个是float浮动布局导致的,如果不用这个布局就不会有这个问题,我们要做的是,清楚浮动给子元素带来的影响。

我这里有个通俗的理解,所有的元素是左浮动,那么每个元素都会尽可能地去贴上一个元素的右边。比方说2会去贴1,3会去贴2。由于1的高度变化了,比2和3要长,那么4正好是可以贴上去的,所以4会贴1,然后原本4的位置被1占用了,4就只能靠右占5的位置,5就占6,以此类推。

要想解决这个问题,那就是强行让4不要去贴1的边。

所以最终的解决方案是,给受到影响的换行子元素,加上clear:left即可。

示例代码如下:

代码语言:html
AI代码解释
复制
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>浮动布局示例</title>
<style>
  .container {
    width: 300px;
    height: 300px;
    border: 1px solid #ccc;
    position: relative;
  }
  .box {
    width: 100px;
    height: 100px;
    float: left;
    text-align: center;
    line-height: 100px;
  }
  .box1 { height:150px;background-color: #ff9999; }
  .box2 { background-color: #ffcc99; }
  .box3 { background-color: #ffff99; }
  .box4 { background-color: #ccff99; }
  .box5 { background-color: #99ffcc; }
  .box6 { background-color: #99ccff; }
  .box7 { background-color: #cc99ff; }
  .box8 { background-color: #ff99cc; }
  .box9 { background-color: #cccccc; }
  .box:nth-child(3n+1){
    clear: left
  }
</style>
</head>
<body>

<div class="container">
  <div class="box box1">1</div>
  <div class="box box2">2</div>
  <div class="box box3">3</div>
  <div class="box box4">4</div>
  <div class="box box5">5</div>
  <div class="box box6">6</div>
  <div class="box box7">7</div>
  <div class="box box8">8</div>
  <div class="box box9">9</div>
</div>

</body>
</html>

效果如下:

关键是要给3n+1个子元素加上清除左浮动,防止后续其他元素高度变化后,出现类似的问题。

实际案例

我开发的项目中,用到了ant-design-vue 1.7.8这个前端UI框架,里面的formModel表单,表单项用到的就是float布局。

这里有个示例代码,可以复现这个问题。

代码语言:html
AI代码解释
复制
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ant Design Vue 表单示例</title>
<!-- 引入 Vue 和 Ant Design Vue 1.7.8 的 CDN -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/ant-design-vue/1.7.8/antd.min.css">
<script src="https://cdn.bootcdn.net/ajax/libs/ant-design-vue/1.7.8/antd.min.js"></script>
</head>
<body>
<div id="app">
  <a-form-model
    ref="formModel"
    :model="form"
    :rules="rules"
    layout="inline"
  >
    <a-row :gutter="24">
      <!-- 多选 Select -->
      <a-col :span="12">
        <a-form-model-item label="兴趣爱好" name="hobbies">
          <a-select
            v-model="form.hobbies"
            mode="multiple"
            placeholder="请选择你的兴趣爱好"
            allow-clear
            style="width:340px"
          >
            <a-select-option v-for="item in options" :key="item.value" :value="item.value">
              {{ item.label }}
            </a-select-option>
          </a-select>
        </a-form-model-item>
      </a-col>

      <!-- 输入框 -->
      <a-col :span="12">
        <a-form-model-item label="姓名" name="name">
          <a-input v-model="form.name" placeholder="请输入姓名"></a-input>
        </a-form-model-item>
      </a-col>

      <!-- 数字输入框 -->
      <a-col :span="12">
        <a-form-model-item label="年龄" name="age">
          <a-input-number v-model="form.age" placeholder="请输入年龄" style="width: 100%;"></a-input-number>
        </a-form-model-item>
      </a-col>

      <!-- 单选框组 -->
      <a-col :span="12">
        <a-form-model-item label="性别" name="gender">
          <a-radio-group v-model="form.gender">
            <a-radio value="male"></a-radio>
            <a-radio value="female"></a-radio>
          </a-radio-group>
        </a-form-model-item>
      </a-col>

      <!-- 日期选择器 -->
      <a-col :span="12">
        <a-form-model-item label="生日" name="birthday">
          <a-input v-model="form.birthday" placeholder="选择日期"></a-input>
        </a-form-model-item>
      </a-col>

      <!-- 开关 -->
      <a-col :span="12">
        <a-form-model-item label="是否订阅" name="subscribe">
          <a-switch v-model="form.subscribe"></a-switch>
        </a-form-model-item>
      </a-col>

      <!-- 滑块 -->
      <a-col :span="12">
        <a-form-model-item label="满意度" name="satisfaction">
          <a-slider v-model="form.satisfaction"></a-slider>
        </a-form-model-item>
      </a-col>
      
      <!-- 滑块 -->
      <a-col :span="12">
        <a-form-model-item label="满意度" name="satisfaction">
          <a-slider v-model="form.satisfaction"></a-slider>
        </a-form-model-item>
      </a-col>

      <!-- 提交与重置按钮 -->
      <a-col :span="24">
        <a-form-model-item>
          <a-button type="primary" @click="handleSubmit">提交</a-button>
          <a-button style="margin-left: 10px;" @click="handleReset">重置</a-button>
        </a-form-model-item>
      </a-col>
    </a-row>
  </a-form-model>
</div>

<script>
  new Vue({
    el: '#app',
    data() {
      return {
        form: {
          hobbies: [],
          name: '',
          age: null,
          gender: '',
          birthday: null,
          subscribe: false,
          satisfaction: 0,
        },
        rules: {
          hobbies: [{ required: true, message: '请选择至少一个兴趣爱好', type: 'array' }],
          name: [{ required: true, message: '请输入姓名' }],
          age: [{ type: 'number', required: true, message: '请输入年龄' }],
          gender: [{ required: true, message: '请选择性别' }],
          birthday: [{ required: true, message: '请选择生日' }],
        },
        options: Array.from({ length: 20 }, (_, index) => ({
          value: `option-${index + 1}`,
          label: `选项 ${index + 1}`,
        })),
      };
    },
    methods: {
      handleSubmit() {
        this.$message.success('表单提交成功:' + JSON.stringify(this.form));
      },
      handleReset() {
        this.$refs.formModel.resetFields();
        this.$message.info('表单已重置');
      },
    },
  });
</script>
</body>
</html>

效果如下:

咋一看没问题,但只要你在select中多选,选择足够多,多到足以改变高度,问题就出现了。第三个表单项被挤压到了原本第四个元素的位置。

解决办法跟上面一样,设置一个选择器清除左浮动即可。

代码语言:html
AI代码解释
复制
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ant Design Vue 表单示例</title>
<!-- 引入 Vue 和 Ant Design Vue 1.7.8 的 CDN -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/ant-design-vue/1.7.8/antd.min.css">
<script src="https://cdn.bootcdn.net/ajax/libs/ant-design-vue/1.7.8/antd.min.js"></script>
<style>
  .ant-row.form-row .ant-col-12:nth-child(3n){
    clear: left;
  }
</style>
</head>
<body>
<div id="app">
  <a-form-model
    ref="formModel"
    :model="form"
    :rules="rules"
    layout="inline"
  >
    <a-row :gutter="24" class="form-row">
      <!-- 多选 Select -->
      <a-col :span="12">
        <a-form-model-item label="兴趣爱好" name="hobbies">
          <a-select
            v-model="form.hobbies"
            mode="multiple"
            placeholder="请选择你的兴趣爱好"
            allow-clear
            style="width:340px"
          >
            <a-select-option v-for="item in options" :key="item.value" :value="item.value">
              {{ item.label }}
            </a-select-option>
          </a-select>
        </a-form-model-item>
      </a-col>

      <!-- 输入框 -->
      <a-col :span="12">
        <a-form-model-item label="姓名" name="name">
          <a-input v-model="form.name" placeholder="请输入姓名"></a-input>
        </a-form-model-item>
      </a-col>

      <!-- 数字输入框 -->
      <a-col :span="12">
        <a-form-model-item label="年龄" name="age">
          <a-input-number v-model="form.age" placeholder="请输入年龄" style="width: 100%;"></a-input-number>
        </a-form-model-item>
      </a-col>

      <!-- 单选框组 -->
      <a-col :span="12">
        <a-form-model-item label="性别" name="gender">
          <a-radio-group v-model="form.gender">
            <a-radio value="male"></a-radio>
            <a-radio value="female"></a-radio>
          </a-radio-group>
        </a-form-model-item>
      </a-col>

      <!-- 日期选择器 -->
      <a-col :span="12">
        <a-form-model-item label="生日" name="birthday">
          <a-input v-model="form.birthday" placeholder="选择日期"></a-input>
        </a-form-model-item>
      </a-col>

      <!-- 开关 -->
      <a-col :span="12">
        <a-form-model-item label="是否订阅" name="subscribe">
          <a-switch v-model="form.subscribe"></a-switch>
        </a-form-model-item>
      </a-col>

      <!-- 滑块 -->
      <a-col :span="12">
        <a-form-model-item label="满意度" name="satisfaction">
          <a-slider v-model="form.satisfaction"></a-slider>
        </a-form-model-item>
      </a-col>
      
      <!-- 滑块 -->
      <a-col :span="12">
        <a-form-model-item label="满意度" name="satisfaction">
          <a-slider v-model="form.satisfaction"></a-slider>
        </a-form-model-item>
      </a-col>

      <!-- 提交与重置按钮 -->
      <a-col :span="24">
        <a-form-model-item>
          <a-button type="primary" @click="handleSubmit">提交</a-button>
          <a-button style="margin-left: 10px;" @click="handleReset">重置</a-button>
        </a-form-model-item>
      </a-col>
    </a-row>
  </a-form-model>
</div>

<script>
  new Vue({
    el: '#app',
    data() {
      return {
        form: {
          hobbies: [],
          name: '',
          age: null,
          gender: '',
          birthday: null,
          subscribe: false,
          satisfaction: 0,
        },
        rules: {
          hobbies: [{ required: true, message: '请选择至少一个兴趣爱好', type: 'array' }],
          name: [{ required: true, message: '请输入姓名' }],
          age: [{ type: 'number', required: true, message: '请输入年龄' }],
          gender: [{ required: true, message: '请选择性别' }],
          birthday: [{ required: true, message: '请选择生日' }],
        },
        options: Array.from({ length: 20 }, (_, index) => ({
          value: `option-${index + 1}`,
          label: `选项 ${index + 1}`,
        })),
      };
    },
    methods: {
      handleSubmit() {
        this.$message.success('表单提交成功:' + JSON.stringify(this.form));
      },
      handleReset() {
        this.$refs.formModel.resetFields();
        this.$message.info('表单已重置');
      },
    },
  });
</script>
</body>
</html>

这样就改好了!

总结

这类问题的解决办法,最好是从源头解决。我曾经尝试过换布局,但这样改动量会比较大,不是很合适。关于float清除浮动的实际含义,可以看看张鑫旭大佬的文章,我放到参考链接里面了。

参考

CSS篇—— 如何解决 float 元素浮动后高度不一致导致错位的问题 · Issue #340 · iuap-design/blog

准确理解CSS clear:left/right的含义及实际用途 « 张鑫旭-鑫空间-鑫生活

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
3 条评论
热度
最新
好内容,赞👍
好内容,赞👍
111举报
谢谢支持
谢谢支持
回复回复点赞举报
666
666
回复回复1举报
推荐阅读
编辑精选文章
换一批
vue快速学习03、ant-design
包含内容:antd.min.css、antd.min.js、vue.min.js。
红目香薰
2022/11/30
7840
vue快速学习03、ant-design
【wiki知识库】06.文档管理页面的添加--前端Vue部分
在此之前我要要说一件事情,我在做这个模块的时候出现了问题,一个是我们之后要使用的文本编辑器wangeditor无法正常展示,还有一个是弹窗无法关闭的问题。这里我把解决方法告诉大家。
哈__
2024/06/10
1870
【wiki知识库】06.文档管理页面的添加--前端Vue部分
讲了个免费的前端项目,小白也能学!
大家好,我是程序员鱼皮。很多朋友都知道,我从 22 年开始带大家做项目,至今已经练习两年半、带做了 10 多套项目。虽然不断产出新项目,但随着时间的流逝和技术的更新,早期录制的项目教程的含金量也会慢慢减少。
程序员鱼皮
2024/12/19
1840
讲了个免费的前端项目,小白也能学!
48·灵魂前端工程师养成-Vue表单和v-model
-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。
DriverZeng
2022/11/08
5840
48·灵魂前端工程师养成-Vue表单和v-model
木字楠后台管理系统开发(5):Vue登陆界面编写以及与后台联调测试
木字楠
2023/10/17
2240
木字楠后台管理系统开发(5):Vue登陆界面编写以及与后台联调测试
基于Ant Design Vue封装一个表单控件
https://github.com/naturefwvue/nf-vue3-ant
用户1174620
2020/09/19
3.2K0
Vue 折腾记 - (16) 基于Ant Design Vue 封装一个配置式的表单搜索组件
React 折腾记 - (6) 基于React 16.x+ Antd 3.封装的一个声明式的查询组件(实用强大)
CRPER
2019/04/18
8.5K0
Vue 折腾记 - (16) 基于Ant Design Vue 封装一个配置式的表单搜索组件
如果你觉得写代码很难,那么请认真读完这篇文章,会让你找到coding的正确姿势!
秒变正经,进入正题,其实还是围绕Ant Design Vue中组件的使用展开,相信我,这并不难。
软件测试君
2022/03/31
7550
如果你觉得写代码很难,那么请认真读完这篇文章,会让你找到coding的正确姿势!
前端VUE【实战】—— antd tree树形控件进行增删改查父子节点
最近在用Ant Design写一个后台,遇到的需求就是实现一个可动态增减和编辑子节点的Tree。
江一铭
2022/06/17
2.3K0
前端VUE【实战】—— antd tree树形控件进行增删改查父子节点
【wiki知识库】05.分类管理实现--前端Vue模块
除了分类管理,我们的首页也变动了一下。首页的导航栏加载的是我们已经有的分类,同时还加上了一个欢迎页面。
哈__
2024/06/06
1220
【wiki知识库】05.分类管理实现--前端Vue模块
在业务代码中常用到的Vue数据通信方式
本文是笔者总结过往项目,在vue使用到的一些数据通信方案,希望在实际项目中有些帮助和思考。
Maic
2022/07/28
5.1K0
在业务代码中常用到的Vue数据通信方式
antdv动态表单组件
分享一个自己写的antdv动态表单组件 <!-- 动态表单组件 --> <template> <div> <div v-for="(item, index) in value" :key="item[rowKey] || index"> <a-row> <a-col :span="24"> <slot :item="item"> <a-row v-if="column.length" v-bind="flex">
阿超
2022/08/21
9590
antdv动态表单组件
Element-UI快速入门
https://element.eleme.cn/#/zh-CN/component/installation
陶然同学
2023/02/24
4.3K0
Element-UI快速入门
【wiki知识库】07.用户管理前端模块的添加-前端部分
这一部分的内容不再多说了,添加一个菜单很简单,只需要在文件中多加一个item,然后item中加上一个路由跳转的标签。最后在配置一下路由就可以了。
哈__
2024/08/06
960
【wiki知识库】07.用户管理前端模块的添加-前端部分
Ant Design Vue使用中的注意项
https://1.x.antdv.com/components/form-cn/
码客说
2021/11/10
1.5K0
Ant Design Vue使用中的注意项
Vue3项目-生成Cron表达式组件
  最近做的一个vue3项目过程中,需要用到cron表达式功能,而对于普通业务人员,他们是不懂cron表达式规则的,所以需要做一个可手动配置生成cron表达式的功能。从网上查找了一些相关资料,然后结合vue3+Element Plus,改造成适合自己项目的组件。记录代码如下:
用户1174387
2022/12/18
5.5K9
Vue3项目-生成Cron表达式组件
Python-drf前戏38.1-前端Vue01
-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。
DriverZeng
2022/09/26
2.7K0
Vue项目引入百度地图
先去百度开放平台申请ak。百度地图开放平台 | 百度地图API SDK | 地图开发
用户10175992
2022/11/15
6550
Vue项目引入百度地图
vue 页面逻辑复用
在开发表单页面时, 经常碰到一种情况。 同一表单存在 新建 编辑 查看 几种状态。页面的大体组成基本相同,但又需要做部分针对当前状态的处理,处理这类问题,一般存在两种方式
copy_left
2019/08/29
1.5K0
【wiki知识库】04.SpringBoot后端实现电子书的增删改查以及前端界面的展示
今天主要是把这个网页的界面初步优化一下,修改一下导航栏以及增加电子书管理模块。包含电子书的查询功能、新增功能、编辑功能和删除功能(不包括文档管理)。
哈__
2024/06/04
1540
【wiki知识库】04.SpringBoot后端实现电子书的增删改查以及前端界面的展示
推荐阅读
相关推荐
vue快速学习03、ant-design
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文