css - Vuetify v-select 组件宽度改变

标签 css vue.js vuetify.js v-select

我的 v-select组件应该有一个固定的宽度(60px),它们适合一个表格单元格,我想防止它们在选择值后改变宽度。
他们改变宽度,选择后下拉箭头向右移动,所以如果有办法减小图标的大小或其填充/边距,它可能会有所帮助。
真的不知道如何获得这个箭头的 Prop 以及它是如何调用的。
这是可重现的
https://codesandbox.io/s/competent-dew-eixq2?file=/src/components/Playground.vue
编辑:添加片段

<!DOCTYPE html>
<html>

<head>
  <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/vuetify@2.0.1/dist/vuetify.min.css" rel="stylesheet">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
  <style>
    .select {
      max-width: 60px;
      max-height: 60px;
      font-size: 11px;
    }
    
    .col {
      max-width: 60px;
      max-height: 60px;
    }
  </style>
</head>

<body>
  <div id="app">
    <v-app>
      <v-row>
        <div class="col" v-for="col in cols" :key="col">
          <v-select class="select" :items="variants" item-value="name" item-text="name" label="" dense outlined hide-details single-line v-model="selected">
          </v-select>
        </div>
      </v-row>
    </v-app>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vuetify@2.0.1/dist/vuetify.js"></script>
  <script>
    new Vue({
      el: '#app',
      vuetify: new Vuetify(),
      data: {
        selected: "",
        cols: [1, 2, 3, 4, 5],
        variants: [{
            id: 0,
            name: ""
          },
          {
            id: 1,
            name: "1:0"
          },
          {
            id: 2,
            name: "0:1"
          },
          {
            id: 3,
            name: "1:0 B"
          },
          {
            id: 4,
            name: "0:1 B"
          },
          {
            id: 6,
            name: "1:0 R"
          },
          {
            id: 7,
            name: "0:1 R"
          },
          {
            id: 8,
            name: "1:0 F"
          },
          {
            id: 9,
            name: "0:1 F"
          },
        ],
      },
    })
  </script>
</body>

</html>

最佳答案

基本问题是 v-select 有一些样式(特别是填充和边距)在小宽度下效果不佳。
这是渲染出来的v-select的innerHTML,需要减少的样式

<div class="select...">                                      
  <div class="v-input__control">
    <div role="button" class="v-input__slot">                <!-- padding-right: 12px; -->
      <div class="v-select__slot">
        <div class="v-select__selections">                               
          <div class="v-select__selection--comma">           <!-- margin-right: 4px; -->
            1:0 B
          </div>
        </div>
        <div class="v-input__append-inner">                  <!-- padding-left: 4px; -->
          <div class="v-input__icon v-input__icon--append">  <!-- width: 24px; min-width: 24px;-->
            <i aria-hidden="true" class="v-icon..."></i>                 
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
除了那些innerHTML更改之外,您还需要每列60px的固定宽度,因此请更改
<style>
  .select {
    max-width: 60px;
    ...
  }
<style>
  .select {
    width: 60px;
    ...
  }

调整 Vuetify 内部样式
查看围绕样式的 Vuetify 问题,有人建议使用非范围样式块或深范围样式块,但都不适合我。 Vuetify 表示他们正在努力改进应用样式的方式来克服这些问题。
幸运的是 Vue 本身有工具可以在 javascript 中做到这一点。
这些是关键步骤
  • 添加对 v-select 的引用,以便它可以在 javascript
  • 中访问
  • 向 v-select 添加更改处理程序,以便在用户选择某些内容时可以重新设置元素的样式
  • 在对象中定义样式调整,以便您可以轻松调整它们
  • 添加应用样式的方法
  • 调用 mounted() 中的方法和 v-select @change处理程序
  • 使用 Vue.nextTick()首先允许 Vuetify 设置样式,然后应用我们的自定义样式

  • 这是调整后的代码片段。我放入了一些非常小的填充和边距,并最大化所选值的空间(以避免文本换行)。您可能想尝试一下这些样式,因为我不确定我是否理解所有要求。

    <!DOCTYPE html>
    <html>
    
    <head>
      <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
      <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
      <link href="https://cdn.jsdelivr.net/npm/vuetify@2.0.1/dist/vuetify.min.css" rel="stylesheet">
      <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
      <style>
        .select {
          width: 60px;
          max-height: 60px;
          font-size: 11px;
        }
        
        .col {
          max-width: 60px;
          max-height: 60px;
        }
      </style>
    </head>
    
    <body>
      <div id="app">
        <v-app>
          <v-row>
            <div class="col" v-for="col in cols" :key="col">
              <v-select ref="select" @change="applyCustomStyles"
     class="select" :items="variants" item-value="name" item-text="name" label="" dense outlined hide-details single-line v-model="selected">
              </v-select>
            </div>
          </v-row>
        </v-app>
      </div>
    
      <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/vuetify@2.0.1/dist/vuetify.js"></script>
      <script>
        const customStyles = {
          ".v-input__slot": {
            padding: "0 0 0 4px",
          },
          ".v-select__selections": {
            width: "27px",
          },
          ".v-select__selection--comma": {
            margin: "7px 0 7px 0",
          },
          ".v-input__append-inner": {
            "padding-left": "0",
          },
          ".v-input__icon": {
            width: "14px",
            "min-width": "14px",
          },
        };
    
        new Vue({
          el: '#app',
          vuetify: new Vuetify(),
          mounted() {
            this.applyCustomStyles();
          },
          methods: {
            applyCustomStyles() {
              Vue.nextTick(() => {
                this.$refs.select.forEach((vSelect) => {
                  Object.entries(customStyles).forEach(([selector, styles]) => {
                    Object.entries(styles).forEach(([style, value]) => {
                      vSelect.$el.querySelector(selector).style[style] = value;
                    });
                  });
                });
              });
            },
          },
          data: {
            selected: "",
            cols: [1, 2, 3, 4, 5],
            variants: [{
                id: 0,
                name: ""
              },
              {
                id: 1,
                name: "1:0"
              },
              {
                id: 2,
                name: "0:1"
              },
              {
                id: 3,
                name: "1:0 B"
              },
              {
                id: 4,
                name: "0:1 B"
              },
              {
                id: 6,
                name: "1:0 R"
              },
              {
                id: 7,
                name: "0:1 R"
              },
              {
                id: 8,
                name: "1:0 F"
              },
              {
                id: 9,
                name: "0:1 F"
              },
            ],
          },
        })
      </script>
    </body>
    
    </html>


    为什么不是 <style>堵塞?
    有使用无作用域样式块来覆盖 Vuetify 样式的建议。
    例如,
    <style>
      .select .v-input__slot {
       padding-right: 4px
      }
      ...
    </style>
    
    问题是 Vuetify 样式是在组件上声明的样式之后应用的。
    enter image description here
    您可以通过应用比 Vuetify 使用更大的特异性来做到这一点,例如
    <style>
      .select.v-text-field.v-text-field--enclosed:not(.v-text-field--rounded)>.v-input__control>.v-input__slot {
      padding-right: 4px
    }
    </style>
    
    给你这个
    enter image description here
    因此您可以找出所有需要更改的现有位置并复制 Vuetify 选择器。
    当使用新版本的 Vuetify 或更改组件的形状时,可能会出现问题。对我来说,javascript 解决方案看起来更易于管理。

    关于css - Vuetify v-select 组件宽度改变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68074520/

    相关文章:

    jquery - 仅限 iOS 上的圆形 div/按钮??? jQuery、ajax、CSS

    css - 无法通过 iPhone 上的 HTML5 视频元素访问文本字段

    vue.js - 在 Vue.js 中,如何在单独的文件中编写自定义过滤器并通过在 main.js 中声明在各种组件中使用它们?

    vue.js - Vuetify/嵌套验证

    python - 用 selenium 和 python 单击特殊按钮

    javascript - 如何调整 100% 高度以包含添加元素的高度

    javascript - 使用 Vue.js 和 Firebase 进行验证

    javascript - 为什么 Vue 将未指定的 bool props 视为 false?

    html - 如何在 y 轴上将左右列内容相互对齐?

    vuejs2 - 如何在 `transition-group` 中设置属性或 Prop