Vue3栅格(Grid)

news2024/11/26 10:19:21

24 栅格系统

概述

布局的栅格化系统,我们是基于行(Row)和列(Col)两个组件相互配合来定义信息区块的外部框架,以保证页面的每个区域能够稳健地排布起来。
下面简单介绍一下它的工作原理:

  • 通过Row在水平方向建立一组Col
  • 你的内容应当放置于Col内,并且,只有Col可以作为Row的直接元素
  • 栅格系统中的列是指 1 到 24 的值来表示其跨越的范围。例如,三个等宽的- 列可以使用 :span="8" 来创建
  • 如果一个Row中的Col总和超过 24,那么多余的Col会作为一个整体另起一行排列

Flex 布局

我们的栅格化系统支持 Flex 布局,允许子元素在父节点内的水平对齐方式 - 居左、居中、居右、等宽排列、分散排列。子元素与子元素之间,支持顶部对齐、垂直居中对齐、底部对齐的方式。同时,支持使用 order 来定义元素的排列顺序。 Flex 布局是基于 24 栅格来定义每一个『盒子』的宽度,但不拘泥于栅格

😁 整体功能效果与 ant design vue 保持高度一致 😁

1. 行组件Row.vue

可自定义设置以下属性:

  • 行宽度(width),类型:string|number,默认:‘auto’
  • 栅格间隔(gutter),类型:number|[number|Responsive, number|Responsive]|Responsive,默认值:0。可以写成像素值或支持响应式的对象写法来设置水平间隔 { xs: 8, sm: 16, md: 24}。或者使用数组形式同时设置 [水平间距, 垂直间距],推荐使用 (16+8n)px 作为栅格间隔(n 是自然数:0,1,2,3…)
  • 是否自动换行(wrap),类型:boolean,默认值:false
  • 垂直对齐方式(align),类型:‘top’|‘middle’|‘bottom’|‘stretch’,默认:‘top’
  • 水平排列方式(justify),类型:‘start’|‘end’|‘center’|‘space-around’|‘space-between’|‘space-evenly’,默认:‘start’

其中 type Responsive

interface Responsive {
  xs?: number // <576px 响应式栅格
  sm?: number // ≥576px 响应式栅格
  md?: number // ≥768px 响应式栅格
  lg?: number // ≥992px 响应式栅格
  xl?: number // ≥1200px 响应式栅格
  xxl?: number // ≥1600px 响应式栅格
}

2. 列组件Col.vue

可自定义设置以下属性:

  • 栅格占位格数(span),类型:number,默认:undefined。为 0 时相当于 display: none,取0,1,2…24
  • 栅格左侧的间隔格数(offset),类型:number,默认:0。取0,1,2…24
  • flex 布局填充(flex),类型:string|number,默认:‘’
  • <576px 响应式栅格(xs),类型:number|{span: number, offset?: number},默认:undefined
  • ≥576px 响应式栅格(sm),类型:number|{span: number, offset?: number},默认:undefined
  • ≥768px 响应式栅格(md),类型:number|{span: number, offset?: number},默认:undefined
  • ≥992px 响应式栅格(lg),类型:number|{span: number, offset?: number},默认:undefined
  • ≥1200px 响应式栅格(xl),类型:number|{span: number, offset?: number},默认:undefined
  • ≥1600px 响应式栅格(xxl),类型:number|{span: number, offset?: number},默认:undefined

效果如下图:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

创建行组件Row.vue

<script setup lang="ts">
import { onMounted, onUnmounted, ref, computed } from 'vue'
interface Responsive {
  xs?: number // <576px 响应式栅格
  sm?: number // ≥576px 响应式栅格
  md?: number // ≥768px 响应式栅格
  lg?: number // ≥992px 响应式栅格
  xl?: number // ≥1200px 响应式栅格
  xxl?: number // ≥1600px 响应式栅格
}
interface Props {
  width?: string|number // 行宽度
  // 推荐使用 (16+8n)px 作为栅格间隔(n 是自然数:0,1,2,3...)
  gutter?: number|[number|Responsive, number|Responsive]|Responsive // 栅格间隔,可以写成像素值或支持响应式的对象写法来设置水平间隔 { xs: 8, sm: 16, md: 24}。或者使用数组形式同时设置 [水平间距, 垂直间距]
  wrap?: boolean // 是否自动换行
  align?: 'top'|'middle'|'bottom'|'stretch' // 垂直对齐方式
  justify?: 'start'|'end'|'center'|'space-around'|'space-between'|'space-evenly' // 水平排列方式
}
const props = withDefaults(defineProps<Props>(), {
  width: 'auto',
  gutter: 0,
  wrap: false,
  align: 'top',
  justify: 'start'
})
const alignProperties = {
  top: 'flex-start',
  middle: 'center',
  bottom: 'flex-end',
  stretch: 'stretch'
}
const xGap = computed(() => {
  if (typeof props.gutter === 'number') {
    return props.gutter
  }
  if (Array.isArray(props.gutter)) {
    if (typeof props.gutter[0] === 'object') {
      if (clientWidth.value >= 1600 && props.gutter[0].xxl) {
        return props.gutter[0].xxl
      }
      if (clientWidth.value >= 1200 && props.gutter[0].xl) {
        return props.gutter[0].xl
      }
      if (clientWidth.value >= 992 && props.gutter[0].lg) {
        return props.gutter[0].lg
      }
      if (clientWidth.value >= 768 && props.gutter[0].md) {
        return props.gutter[0].md
      }
      if (clientWidth.value >= 576 && props.gutter[0].sm) {
        return props.gutter[0].sm
      }
      if (clientWidth.value < 576 && props.gutter[0].xs) {
        return props.gutter[0].xs
      }
    }
    return props.gutter[0]
  }
  if (typeof props.gutter === 'object') {
    if (clientWidth.value >= 1600 && props.gutter.xxl) {
      return props.gutter.xxl
    }
    if (clientWidth.value >= 1200 && props.gutter.xl) {
      return props.gutter.xl
    }
    if (clientWidth.value >= 992 && props.gutter.lg) {
      return props.gutter.lg
    }
    if (clientWidth.value >= 768 && props.gutter.md) {
      return props.gutter.md
    }
    if (clientWidth.value >= 576 && props.gutter.sm) {
      return props.gutter.sm
    }
    if (clientWidth.value < 576 && props.gutter.xs) {
      return props.gutter.xs
    }
  }
  return 0
})
const yGap = computed(() => {
  if (Array.isArray(props.gutter)) {
    if (typeof props.gutter[1] === 'object') {
      if (clientWidth.value >= 1600 && props.gutter[1].xxl) {
        return props.gutter[1].xxl
      }
      if (clientWidth.value >= 1200 && props.gutter[1].xl) {
        return props.gutter[1].xl
      }
      if (clientWidth.value >= 992 && props.gutter[1].lg) {
        return props.gutter[1].lg
      }
      if (clientWidth.value >= 768 && props.gutter[1].md) {
        return props.gutter[1].md
      }
      if (clientWidth.value >= 576 && props.gutter[1].sm) {
        return props.gutter[1].sm
      }
      if (clientWidth.value < 576 && props.gutter[1].xs) {
        return props.gutter[1].xs
      }
    }
    return props.gutter[1]
  }
  return 0
})
const rowWidth = computed(() => {
  if (typeof props.width === 'number') {
    return props.width + 'px'
  }
  return props.width
})
const clientWidth = ref(document.documentElement.clientWidth)
onMounted(() => {
  window.addEventListener('resize', getBrowserSize)
})
onUnmounted(() => {
  window.removeEventListener('resize', getBrowserSize)
})
function getBrowserSize () {
  // document.documentElement返回<html>元素
  clientWidth.value = document.documentElement.clientWidth
}
</script>
<template>
  <div
    class="m-row"
    :class="{'gutter-row': gutter}"
    :style="`--xGap: ${(xGap as number) / 2}px; --justify: ${justify}; --align: ${alignProperties[align]}; width: ${rowWidth}; margin-left: -${(xGap as number) / 2}px; margin-right: -${(xGap as number) / 2}px; row-gap: ${yGap}px;`">
    <slot></slot>
  </div>
</template>
<style lang="less" scoped>
.m-row {
  display: flex;
  flex-flow: row wrap;
  justify-content: var(--justify);
  align-items: var(--align);
  min-width: 0;
  font-size: 14px;
  color: rgba(0, 0, 0, 0.88);
  transition: all .3s;
}
</style>

创建列组件Col.vue

<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed } from 'vue'
interface Props {
  span?: number // 栅格占位格数,为 0 时相当于 display: none,取0,1,2...24
  offset?: number // 栅格左侧的间隔格数,取0,1,2...24
  flex?: string|number //	flex 布局填充
  xs?: number|{span: number, offset?: number} // <576px 响应式栅格
  sm?: number|{span: number, offset?: number} // ≥576px 响应式栅格
  md?: number|{span: number, offset?: number} // ≥768px 响应式栅格
  lg?: number|{span: number, offset?: number} // ≥992px 响应式栅格
  xl?: number|{span: number, offset?: number} // ≥1200px 响应式栅格
  xxl?: number|{span: number, offset?: number} // ≥1600px 响应式栅格
}
const props = withDefaults(defineProps<Props>(), {
  span: undefined,
  offset: 0,
  flex: '',
  xs: undefined,
  sm: undefined,
  md: undefined,
  lg: undefined,
  xl: undefined,
  xxl: undefined
})
const flexValue = computed(() => {
  if (typeof props.flex === 'number') {
    return `${props.flex} ${props.flex} auto`
  }
  return props.flex
})
const responsiveProperty = computed(() => {
  if (clientWidth.value >= 1600 && props.xxl) {
    if (typeof props.xxl === 'object') {
      return props.xxl
    } else {
      return {
        span: props.xxl,
        offset: undefined
      }
    }
  }
  if (clientWidth.value >= 1200 && props.xl) {
    if (typeof props.xl === 'object') {
      return props.xl
    } else {
      return {
        span: props.xl,
        offset: undefined
      }
    }
  }
  if (clientWidth.value >= 992 && props.lg) {
    if (typeof props.lg === 'object') {
      return props.lg
    } else {
      return {
        span: props.lg,
        offset: undefined
      }
    }
  }
  if (clientWidth.value >= 768 && props.md) {
    if (typeof props.md === 'object') {
      return props.md
    } else {
      return {
        span: props.md,
        offset: undefined
      }
    }
  }
  if (clientWidth.value >= 576 && props.sm) {
    if (typeof props.sm === 'object') {
      return props.sm
    } else {
      return {
        span: props.sm,
        offset: undefined
      }
    }
  }
  if (clientWidth.value < 576 && props.xs) {
    if (typeof props.xs === 'object') {
      return props.xs
    } else {
      return {
        span: props.xs,
        offset: undefined
      }
    }
  }
})
const clientWidth = ref(document.documentElement.clientWidth)
onMounted(() => {
  window.addEventListener('resize', getBrowserSize)
})
onUnmounted(() => {
  window.removeEventListener('resize', getBrowserSize)
})
function getBrowserSize () {
  // document.documentElement返回<html>元素
  clientWidth.value = document.documentElement.clientWidth
}
</script>
<template>
  <div
    :class="`m-col col-${responsiveProperty?.span || span} offset-${responsiveProperty?.offset || offset}`"
    style="padding-left: var(--xGap); padding-right: var(--xGap);"
    :style="`flex: ${flexValue}`">
    <slot></slot>
  </div>
</template>
<style lang="less" scoped>
.m-col {
  position: relative;
  max-width: 100%;
  min-height: 1px;
  font-size: 14px;
  color: rgba(0, 0, 0, 0.88);
  line-height: 1.5714285714285714;
  transition: all .3s;
}
.col-0 {
  display: none;
}
.col-1 {
  display: block;
  flex: 0 0 4.16666666666666%;
  max-width: 4.16666666666666%;
}
.offset-1 {
  margin-inline-start: 4.16666666666666%;
}
.col-2 {
  display: block;
  flex: 0 0 8.33333333333333%;
  max-width: 8.33333333333333%;
}
.offset-2 {
  margin-inline-start: 8.33333333333333%;
}
.col-3 {
  display: block;
  flex: 0 0 12.5%;
  max-width: 12.5%;
}
.offset-3 {
  margin-inline-start: 12.5%;
}
.col-4 {
  display: block;
  flex: 0 0 16.66666666666666%;
  max-width: 16.66666666666666%;
}
.offset-4 {
  margin-inline-start: 16.66666666666666%;
}
.col-5 {
  display: block;
  flex: 0 0 20.83333333333333%;
  max-width: 20.83333333333333%;
}
.offset-5 {
  margin-inline-start: 20.83333333333333%;
}
.col-6 {
  display: block;
  flex: 0 0 25%;
  max-width: 25%;
}
.offset-6 {
  margin-inline-start: 25%;
}
.col-7 {
  display: block;
  flex: 0 0 29.16666666666666%;
  max-width: 29.16666666666666%;
}
.offset-7 {
  margin-inline-start: 29.16666666666666%;
}
.col-8 {
  display: block;
  flex: 0 0 33.33333333333333%;
  max-width: 33.33333333333333%;
}
.offset-8 {
  margin-inline-start: 33.33333333333333%;
}
.col-9 {
  display: block;
  flex: 0 0 37.5%;
  max-width: 37.5%;
}
.offset-9 {
  margin-inline-start: 37.5%;
}
.col-10 {
  display: block;
  flex: 0 0 41.66666666666666%;
  max-width: 41.66666666666666%;
}
.offset-10 {
  margin-inline-start: 41.66666666666666%;
}
.col-11 {
  display: block;
  flex: 0 0 45.83333333333333%;
  max-width: 45.83333333333333%;
}
.offset-11 {
  margin-inline-start: 45.83333333333333%;
}
.col-12 {
  display: block;
  flex: 0 0 50%;
  max-width: 50%;
}
.offset-12 {
  margin-inline-start: 50%;
}
.col-13 {
  display: block;
  flex: 0 0 54.16666666666666%;
  max-width: 54.16666666666666%;
}
.offset-13 {
  margin-inline-start: 54.16666666666666%;
}
.col-14 {
  display: block;
  flex: 0 0 58.33333333333333%;
  max-width: 58.33333333333333%;
}
.offset-14 {
  margin-inline-start: 58.33333333333333%;
}
.col-15 {
  display: block;
  flex: 0 0 62.5%;
  max-width: 62.5%;
}
.offset-15 {
  margin-inline-start: 62.5%;
}
.col-16 {
  display: block;
  flex: 0 0 66.66666666666666%;
  max-width: 66.66666666666666%;
}
.offset-16 {
  margin-inline-start: 66.6666666666666%;
}
.col-17 {
  display: block;
  flex: 0 0 70.83333333333333%;
  max-width: 70.83333333333333%;
}
.offset-17 {
  margin-inline-start: 70.83333333333333%;
}
.col-18 {
  display: block;
  flex: 0 0 75%;
  max-width: 75%;
}
.offset-18 {
  margin-inline-start: 75%;
}
.col-19 {
  display: block;
  flex: 0 0 79.16666666666666%;
  max-width: 79.16666666666666%;
}
.offset-19 {
  margin-inline-start: 79.16666666666666%;
}
.col-20 {
  display: block;
  flex: 0 0 83.33333333333333%;
  max-width: 83.33333333333333%;
}
.offset-20 {
  margin-inline-start: 83.33333333333333%;
}
.col-21 {
  display: block;
  flex: 0 0 87.5%;
  max-width: 87.5%;
}
.offset-21 {
  margin-inline-start: 87.5%;
}
.col-22 {
  display: block;
  flex: 0 0 91.66666666666666%;
  max-width: 91.66666666666666%;
}
.offset-22 {
  margin-inline-start: 91.66666666666666%;
}
.col-23 {
  display: block;
  flex: 0 0 95.83333333333333%;
  max-width: 95.83333333333333%;
}
.offset-23 {
  margin-inline-start: 95.83333333333333%;
}
.col-24 {
  display: block;
  flex: 0 0 100%;
  max-width: 100%;
}
.offset-24 {
  margin-inline-start: 100%;
}
</style>

在要使用的页面引入

<script setup lang="ts">
import Row from './Row.vue'
import Col from './Col.vue'
</script>
<template>
  <div>
    <h1>Grid 栅格</h1>
    <h2 class="mt30 mb10">基本使用</h2>
    <Row class="row">
      <Col :span="24">col</Col>
    </Row>
    <Row class="row">
      <Col :span="12">col-12</Col>
      <Col :span="12">col-12</Col>
    </Row>
    <Row class="row">
      <Col :span="8">col-8</Col>
      <Col :span="8">col-8</Col>
      <Col :span="8">col-8</Col>
    </Row>
    <Row class="row">
      <Col :span="6">col-6</Col>
      <Col :span="6">col-6</Col>
      <Col :span="6">col-6</Col>
      <Col :span="6">col-6</Col>
    </Row>
    <h2 class="mt30 mb10">水平区块间隔</h2>
    <Row :gutter="16">
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
    </Row>
    <h2 class="mt30 mb10">响应式区块间隔</h2>
    <Row :gutter="{ xs: 8, sm: 16, md: 24, lg: 32 }">
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
    </Row>
    <h2 class="mt30 mb10">垂直区块间隔</h2>
    <Row :gutter="[16, 24]">
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
    </Row>
    <h2 class="mt30 mb10">响应式垂直区块间隔</h2>
    <Row :gutter="[16, { xs: 8, sm: 16, md: 24, lg: 32 }]">
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
      <Col class="gutter-row" :span="6">
        <div class="gutter-box">col-6</div>
      </Col>
    </Row>
    <h2 class="mt30 mb10">左右偏移</h2>
    <Row class="row">
      <Col :span="8">col-8</Col>
      <Col :span="8" :offset="8">col-8</Col>
    </Row>
    <Row class="row">
      <Col :span="6" :offset="6">col-6 col-offset-6</Col>
      <Col :span="6" :offset="6">col-6 col-offset-6</Col>
    </Row>
    <Row class="row">
      <Col :span="12" :offset="6">col-12 col-offset-6</Col>
    </Row>
    <h2 class="mt30 mb10">排版方式</h2>
    <Divider orientation="left">sub-element align left</Divider>
    <Row class="row" justify="start">
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
    </Row>
    <Divider orientation="left">sub-element align center</Divider>
    <Row class="row" justify="center">
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
    </Row>
    <Divider orientation="left">sub-element align right</Divider>
    <Row class="row" justify="end">
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
    </Row>
    <Divider orientation="left">sub-element align space-between</Divider>
    <Row class="row" justify="space-between">
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
    </Row>
    <Divider orientation="left">sub-element align space-around</Divider>
    <Row class="row" justify="space-around">
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
    </Row>
    <Divider orientation="left">sub-element align space-evenly</Divider>
    <Row class="row" justify="space-evenly">
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
      <Col :span="4">col-4</Col>
    </Row>
    <h2 class="mt30 mb10">对齐方式</h2>
    <Divider orientation="left">Align Top</Divider>
    <Row class="row" style="background: rgba(128,128,128,.08);" justify="center" align="top">
      <Col :span="4">
        <p class="height-100">col-4</p>
      </Col>
      <Col :span="4">
        <p class="height-50">col-4</p>
      </Col>
      <Col :span="4">
        <p class="height-120">col-4</p>
      </Col>
      <Col :span="4">
        <p class="height-80">col-4</p>
      </Col>
    </Row>
    <Divider orientation="left">Align Middle</Divider>
    <Row class="row" style="background: rgba(128,128,128,.08);" justify="space-around" align="middle">
      <Col :span="4">
        <p class="height-100">col-4</p>
      </Col>
      <Col :span="4">
        <p class="height-50">col-4</p>
      </Col>
      <Col :span="4">
        <p class="height-120">col-4</p>
      </Col>
      <Col :span="4">
        <p class="height-80">col-4</p>
      </Col>
    </Row>
    <Divider orientation="left">Align Bottom</Divider>
    <Row class="row" style="background: rgba(128,128,128,.08);" justify="space-between" align="bottom">
      <Col :span="4">
        <p class="height-100">col-4</p>
      </Col>
      <Col :span="4">
        <p class="height-50">col-4</p>
      </Col>
      <Col :span="4">
        <p class="height-120">col-4</p>
      </Col>
      <Col :span="4">
        <p class="height-80">col-4</p>
      </Col>
    </Row>
    <h2 class="mt30 mb10">flex 填充</h2>
    <Divider orientation="left">Percentage columns</Divider>
    <Row class="row">
      <Col :flex="2">2 / 5</Col>
      <Col :flex="3">3 / 5</Col>
    </Row>
    <Divider orientation="left">Fill rest</Divider>
    <Row class="row">
      <Col flex="0 0 100px">100px</Col>
      <Col flex="auto">auto</Col>
    </Row>
    <Divider orientation="left">Raw flex style</Divider>
    <Row class="row">
      <Col flex="1 1 200px">1 1 200px</Col>
      <Col flex="0 1 300px">0 1 300px</Col>
    </Row>
    <Row class="row" :wrap="false">
      <Col flex="none">
        <div style="padding: 0 16px">none</div>
      </Col>
      <Col flex="auto">auto with no-wrap</Col>
    </Row>
    <h2 class="mt30 mb10">响应式布局</h2>
    <Row class="row">
      <Col :xs="2" :sm="4" :md="6" :lg="8" :xl="10">Col</Col>
      <Col :xs="20" :sm="16" :md="12" :lg="8" :xl="4">Col</Col>
      <Col :xs="2" :sm="4" :md="6" :lg="8" :xl="10">Col</Col>
    </Row>
    <h2 class="mt30 mb10">span 和 offset 属性的响应式</h2>
    <Row class="row">
      <Col :xs="{ span: 5, offset: 1 }" :sm="{ span: 6, offset: 2 }">Col</Col>
      <Col :xs="{ span: 11, offset: 1 }" :sm="{ span: 6, offset: 2 }">Col</Col>
      <Col :xs="{ span: 5, offset: 1 }" :sm="{ span: 6, offset: 2 }">Col</Col>
    </Row>
  </div>
</template>
<style lang="less" scoped>
.row {
  .m-col {
    min-height: 30px;
    margin-top: 8px;
    margin-bottom: 8px;
    color: #fff;
    text-align: center;
    border-radius: 0;
    padding: 16px 0;
    background: #1677ff;
  }
  :deep(>:nth-child(2n+1)) {
    background: #1677ffbf;
  }
}
.gutter-row {
  .m-col {
    min-height: 30px;
    margin-top: 8px;
    margin-bottom: 8px;
    color: #fff;
    text-align: center;
    border-radius: 0;
  }
  .gutter-box {
    background: #0092ff;
    padding: 8px 0;
  }
  .m-col {
    margin-top: 0;
    margin-bottom: 0;
  }
}
.height-50 {
  height: 50px;
  line-height: 50px;
}
.height-80 {
  height: 80px;
  line-height: 80px;
}
.height-100 {
  height: 100px;
  line-height: 100px;
}
.height-120 {
  height: 120px;
  line-height: 120px;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/770246.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java贪心算法案例

1.零钱找回问题 这个问题在我们的日常生活中就更加普遍了。假设1元、2元、5元、10元、20元、50元、100元的纸币分别有c0, c1, c2, c3, c4, c5, c6张。现在要用这些钱来支付K元&#xff0c;至少要用多少张纸币&#xff1f;用贪心算法的思想&#xff0c;很显然&#xff0c;每一步…

2023年,从0彻底打通自动化测试进阶高级岗,卷起来...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、自动化测试的分…

【设计模式】2、工厂方法模式

文章目录 当你在编写代码的过程中&#xff0c; 如果无法预知对象确切类别及其依赖关系时&#xff0c; 可使用工厂方法。 工厂方法将创建产品的代码与实际使用产品的代码分离&#xff0c; 从而能在不影响其他代码的情况下扩展产品创建部分代码。 例如&#xff0c; 如果需要向应…

Redis的五大数据类型和各自的

- 字符串(String) string 数据结构是简单的 key-value 类型。简单动态字符串**&#xff08;simple dynamic string&#xff0c;SDS&#xff09;。相比于 C 的原生字符串&#xff0c;Redis 的 SDS 不光可以保存文本数据还可以保存二进制数据&#xff0c;并且获取字符串长度复杂度…

手把手教你玩爆破 --- 关于暴力破解的一些故事

今天不是来打游戏的&#xff0c;我们的重点是了解一些针对web登陆界面的爆破手法。 就是在很多场合中上不了台面的一类攻击手法。简单的通过正常请求的发送&#xff0c;不断尝试用户名密码&#xff0c;最终登陆上去的方法。我们可以称之为爆破、穷举攻击。 1.概述 穷举就是枚…

OpenCv之图像金字塔

目录 一、图像金字塔介绍 二、高斯金字塔 三、拉普拉斯金字塔 一、图像金字塔介绍 图像金字塔是图像中多尺度表达的一种&#xff0c;最主要用于图像的分割&#xff0c;是一种以多分辨率来解释图像的有效但概念简单的结构。简单来说&#xff0c;图像金字塔是同一图像不同分辨率…

基于区块链技术的元宇宙游戏将成为时代浪潮的弄潮儿

区块链技术作为互联网新兴技术逐渐走进公众视野&#xff0c;其中心化、分布式、公开透明、不可篡改等技术特性使其可以在各个领域大展拳脚。区块链技术在金融、公益、文化、物流、农业等领域带来了全新的思维视角、全新的场景与全新的解决方案&#xff0c;无疑是移动互联网之后…

Spring Batch之读数据库—JdbcCursorItemReader之自定义PreparedStatementSetter(三十八)

一、自定义PreparedStatementSetter 详情参考我的另一篇博客&#xff1a; Spring Batch之读数据库——JdbcCursorItemReader&#xff08;三十五&#xff09;_人……杰的博客-CSDN博客 二、项目实例 1.项目实例 2.代码实现 BatchMain.java&#xff1a; package com.xj.dem…

推荐10款设计师都在用的3d机械工程软件

新产品和系统的研究和开发需要特定的软件。您必须能够设计建筑物、系统、机械和设备的蓝图和示意图。您还需要能够与其他工程师、绘图员和团队成员协作&#xff0c;同时有效且高效地工作。设计工程师的软件必须简化其流程&#xff0c;以避免妨碍他们的设计和开发工作。 好的工…

SpringBoot项目中WEB与Controller的联系--【SB系列之009】

SpringBoot系列文章目录 SpringBoot 的项目编译即报错处理–SB系列之001 —第一部的其它章节可以通过001链接 ———————————————— SpringBoot项目中WEB页面放哪里–【SB系列之008】SpringBoot项目中WEB与Controller的联系–【SB系列之009】SpringBoot项目中MVC…

喜报|英码科技联合广师大荣获“智芯杯”AI芯片应用创新创业大赛两大奖项

7月15日&#xff0c;由中国仪器仪表学会主办的全国首届“智芯杯”AI芯片应用创新创业大赛总决赛暨颁奖典礼圆满结束&#xff0c;英码科技联合广东技术师范大学设计开发的“AI视觉&#xff0c;让工厂建设更智慧”和“基于AI的智慧校园无感考勤系统”创新项目均荣获三等奖。 ​ 自…

曲师大2023大一新生排位赛-C.String题解

C.String 题目描述 众所周知&#xff0c;许师哥精通字符串。 一天&#xff0c;许师哥意外的获得了一个字符串&#xff0c;但他发现这个字符串并不是一个回文串&#xff0c;因此他非常生气。于是他决定从这个字符串中删除若干个字符使得 剩余的字符串为一个回文串。 回想回文串…

如何选购开放式耳机?开放式蓝牙耳机哪些品牌比较好?开放式耳机选购指南!

作为一个耳机爱好者&#xff0c;最近更是喜欢上了开放式蓝牙耳机&#xff0c;实际用过的起码有十几款&#xff0c;但其实最终能留下来的也只有四五款。由于前期并不知道应该如何选择开放式耳机&#xff0c;经常都会高价买到些质量差、音质也不好、漏音大的开放式耳机&#xff0…

SpringBatch从入门到实战(十一):事务控制

一&#xff1a;事务模型 Step之间事务独立。Step划分成多个Chunk执行&#xff0c;Chunk事务批次独立&#xff0c;互不影响。Chunk开始启动一个事务&#xff0c;Chunk结束时提交或者回滚事务。 二&#xff1a;事务回滚控制 默认情况下&#xff0c;无论是设置了重试retry&#…

实际上手体验maven面对冲突Jar包的加载规则 | 京东云技术团队

一、问题背景 相信大家在日常的开发过程中都遇到过Jar包冲突的问题&#xff0c;emm&#xff0c;在最近处理业务需求时我也遇到了不同版本jar包冲突导致项目加载出错的问题。主要是一个完整的项目会不可避免的使用第三方的Jar包来实现功能开发&#xff0c;各种第三方包之间可能…

低代码如何帮助企业数字化转型?

在数字化时代背景下&#xff0c;企业都面临着巨大的数字化转型挑战。为了迎接这一挑战&#xff0c;企业软件开发工具和平台都在不断地创新和进化。其中&#xff0c;低代码开发平台应运而生&#xff0c;并成为了众多企业转型的首选方案。企业为什么都选择低代码开发平台&#xf…

【机器学习】PyTorch手动实现Logistic算法

参考地址&#xff1a;点击打开 计算较为繁琐&#xff0c;需要用到sigmoid函数和梯度下降算法&#xff0c;步骤主要如下&#xff1a; 二项分布概率公式表示最大似然估计和对数化计算求道带入梯度下降算法计算和优化 代码&#xff1a; import numpy as np import matplotlib.p…

[CPU飙升排查]生产CPU飙升,YGC不断的事故

背景 最近给上线还未使用的服务配置监控,监控系统电话将我呼醒 ,导致原本就不多的头发一阵掉落. 还好系统还没有流量进入,先免打扰,第二天再处理. 查看面板情况如下: FGC正常 YGC不断 CPU飙升 思路确定 分析了下YGC不断,但是没有FGC,CPU飙升,可能出现的情况是哪里有活锁或者…

数据迁移卷不动了?Squids DBMotion新增多种数据库迁移能力

Squdis DBMotion新增了多种数据库的迁移能力&#xff1a;SQLServer to SQLServer、Redis to Redis、MySQL to Kafka&#xff0c;增加了列映射、校验任务独立、抽样校验、校验复检和限速等十多项功能。 本次版本更新&#xff0c;DBMotion新增了三种数据库迁移同步的场景。目前&…

el-table组件插槽“slot-scope”

目录 一、代码展示 二、返回的数组对象不含value或者ispass&#xff0c;不会报错 三、插槽里面放的是要手动输入的值时 一、代码展示 <el-table v-loading"loading" :data"checklistList" selection-change"handleSelectionChange"><…