选择框中的文本填充

56
我在使用 select 下拉框时遇到了一个比较晦涩的问题,文本周围似乎多了一些不属于盒模型的空间。以下是两张图片,可以更好地说明我的意思:
Select Box Padding Test
Select Box Padding Test 2
你可以查看这个在JSFiddle上出现的问题的示例,或者查看我下面提供的示例源代码:
http://jsfiddle.net/hwzd88o5/4/

select, input
{
 padding:0px;
 font-size:20px;
}
select.textIndent
{
 text-indent:-1.5px;
}
select.paddingOffset
{
 padding-left:2.5px;
}
input.paddingOffset
{
 padding-left:5px;
}
<h3>No Padding Test</h3>
<select>
 <option>Item 1</option>
 <option>Item 2</option>
 <option>Item 3</option>
</select><br />
<input type="text" value="Item 1" />
<h3>Negative Text Indent</h3>
<select class="textIndent">
 <option>Item 1</option>
 <option>Item 2</option>
 <option>Item 3</option>
</select><br />
<input type="text" value="Item 1" />
<h3>Padding Offset</h3>
<select class="paddingOffset">
 <option>Item 1</option>
 <option>Item 2</option>
 <option>Item 3</option>
</select><br />
<input class="paddingOffset" type="text" value="Item 1" />

我已经找到了两种方法来解决它,一是使用负的text-indent,二是使用左侧内补白调整inputselect框以匹配对齐。

这两种方法都不完美。Chrome和Firefox上的负的text-indent之间存在差异,如果selectinput在彼此对齐,则会产生明显的空隙。尝试偏移填充可以使维护各种inputselect字段的样式变得有些困难,尤其是当你应用填充的百分比时。

我最初在一个客户网站上注意到这一点,其中单词的一部分被切断,但是如果那个空格不存在,则该单词看起来可以适合。

Client example of the issue

虽然我可以为我的客户解决这个特定问题(例如更宽的select框,更少的内补白),但我想知道是否有另一种解决方案来隐藏/偏移/删除文本左侧/右侧的“其他”填充。是否有其他CSS属性我应该看看?

我有一种感觉这可能只是select框的工作方式,但我希望SO的集体智慧可以证明我错了。

Edit 1

我希望解决方案是纯CSS。我知道如果我使用一个JS库的下拉替换select框,它将不会有相同的问题。

Edit 2

只是为了更好地澄清我的要求,select框在框模型外面有额外的填充。下面的图片显示select框有6px,而input约为3px。我想要控制这个特定的填充或完全删除它。我已经尝试过使用text-indent和使用内补白偏移来对齐inputselect元素中的文本,但这两种方法都似乎是hackish。我认为还有更好的CSS方法来实现这一点。

Example Clarified 1

Example Clarified 2

7个回答

33

很不幸,这些额外的空格是由浏览器呈现引擎添加的。表单元素的呈现在不同浏览器之间是不一致的,在这种情况下,是不受CSS控制的。

看一看Mozilla的这篇文章,介绍了一些缓解选择框不一致性的方法,然后你可以阅读Smashing Magazine的这篇文章,关于表单元素的样式设计(务必查看评论和人们在选择方面遇到的问题)。

编辑2020:我偶然发现了来自CSS-Tricks的Chris Coyer的这篇文章,似乎展示了一些可应用于选择元素的样式设计,可以帮助一些人解决问题。根据Team Treehouse上Liliana Brissos的说法,覆盖浏览器的默认样式比我几年前发布这个答案时意识到的要灵活一些。


谢谢提供这些链接。之前没有在 MDN 上看到过那个页面,非常有用!我真的想看看是否还有其他鲜为人知的 CSS 方法来解决它,但如果没有的话,我会接受你的答案。 - Turnerj
1
没问题!我一直在尝试从供应商那里找到某种文档,以明确特定元素的呈现方式,但没有成功 :( - Jerreck
1
另一个适用于所有浏览器的解决方案是,在选择列表的第一个选项中添加 &nbsp;,请参见这里这里,希望能有所帮助。 - Shaiju T
@stom,抱歉,这根本没有解决问题——如果有什么作用,它实际上会加剧问题。它是select框具有额外的非内容、非边框、非填充“空间”,我们不想再添加任何空间,我们想要删除空间。 - Turnerj

26

您看到的填充来自浏览器特定的样式表。在Chrome中,负责为这些下拉菜单设置样式的属性是-webkit-appearance,而在Firefox中则是-moz-appearance.

您可以通过执行以下操作标准化选择菜单的外观:

select {
    -webkit-appearance: none;
    -moz-appearance : none;
    border:1px solid #ccc;
    border-radius:3px;
    padding:5px 3px;
}

注意: 这不会产生好看的结果,只会给您的选择框提供标准的填充/间距。要实现外观良好、可自定义控制填充/大小等的选择框,有很多教程可以参考。这是我在快速谷歌搜索后找到的一个:

http://www.htmllion.com/default-select-dropdown-style-just-css.html


2
刚刚尝试了您在此fiddle中提供的答案,但我仍然遇到了与我在问题中提到的相同的问题。select框中有一个额外的填充,而input没有。 - Turnerj
2
这不会移除选择框的内部填充。将 padding 更改为 0,以查看文本是否与左侧对齐。 - 3dgoo
5
这并没有减少内容和边框之间的空隙。 - Qi Tang
2
这将会移除 Chrome 中“选择”右侧的图标.. 这不是一个解决方案!此外,与输入框相比,选择框中填充仍然存在问题。 - John

7

左内边距:

  • OS X Chrome 和 Safari = 0 像素;
  • IE 10+ = 2 像素;
  • Edge 17 = 3 像素;
  • OS X FF, Android 4.4 = 4 像素;

这些值可能需要更广泛的跨浏览器测试,我以后可能会更新。我使用了一组CSS hacks来为每个浏览器分配不同的 padding-left 值,使用 calc 和左内边距的“基础”值。例如,如果基础左内边距为 5%,则可以使用以下 SCSS(您可以使用 CSS 预处理器来避免重复):

$select-base-gap-x: 5%;
$select-gap-x: calc(#{$select-base-gap-x} - 4px);
$select-gap-x_edge: calc(#{$select-base-gap-x} - 3px);
$select-gap-x_ie: calc(#{$select-base-gap-x} - 2px);

.select {
  -moz-appearance: none;
  -webkit-appearance: none;
  appearance: none;
  border-radius: 0;
  margin: 0;

  padding-left: $select-gap-x;
  }

/* edge 12-18 */
@supports (-ms-ime-align:auto) {
  .select {
    padding-left: $select-gap-x_edge;
    }
  }

/* ie10-11 */
_:-ms-input-placeholder, :root .select {
  padding-left: $select-gap-x_ie;
  }

/* Chrome 37+ (and Opera 24+) */
@supports (-webkit-appearance:none) and (shape-outside:none) {
  .select {
    // Webkit doesn't need any correction for padding so it uses raw base value
    padding-left: $select-base-gap-x;
    }
  }

/* Safari 6.2,7.1+ */
_::-webkit-full-page-media, _:future, :root .select {
    // Webkit doesn't need any correction for padding so it uses raw base value
    padding-left: $select-base-gap-x;
  }

/* Firefox */
@-moz-document url-prefix() {
  .select {
    // Firefox recognizes hacks for webkit, so it needs a proper padding setting again
    padding-left: $select-gap-x;
    }
  }

这是一个演示链接:https://codepen.io/andreyvolokitin/pen/wvvXZBm


我喜欢你的解决方案。虽然它本质上仍在玩弄填充,但我喜欢使用浏览器奇怪行为(我喜欢那个网站用于一些CSS技巧)与SASS变量的组合 - 甚至可能使用CSS变量。显然,仍然没有像禁用这种“额外填充”怪癖这样的方法那么好,但我喜欢将这些东西结合起来,使这种特定方法更容忍。 - Turnerj

-1
一个不错的选择是用输入数据列表(input datalist)替换选择框(select box)。

-6
要编辑选择框,您必须使用jQuery(或一般的JavaScript)。
无论如何,您可以使用以下“技巧”解决问题:

http://jsfiddle.net/Clear/hwzd88o5/6/

看这里:

select.textIndent
{
    height: 80px;
    line-height: 80px;
    width: 300px;
    padding-left: 50px !important;
}

;)


我认为这不是JS可以修复的问题,除非您是在使用JS完全替换“select”框的另一个元素。我会更新我的问题以澄清。 - Turnerj
好的,你是对的...但是如果你在选择输入框中加入padding: 0;,并根据选择框调整文本输入框,它们就会相等:http://jsfiddle.net/Clear/hwzd88o5/9/ - Davide Scanu
是的,我已经按照我在问题中提到的尝试过了。不幸的是,这种方法并不好,如果我更改其他样式的“input”或“select”元素的填充,我需要继续考虑额外填充。当具有响应式网站并且您在不同屏幕大小上调整边距和填充等内容时,这种情况会被放大。 - Turnerj
1
@DavideScanu。我认为问题中输入框的重点是显示文本与框的侧面对齐,而选择框则不会这样做。 OP正在询问是否有通过CSS使选择框文本在左侧对齐的方法。 - 3dgoo
2
不同浏览器之间存在大小不同的内部填充。虽然内部填充非常小,但在某些情况下它是可见的。OP问是否有一种通过CSS去除此内部填充的方法。我认为你的答案没有回答这个问题。不知道为什么或没有答案是可以的。我也不知道为什么会发生这种情况或如何解决这个问题。 - 3dgoo
显示剩余3条评论

-6

对我而言解决这个问题的方法是覆盖 Chrome 对选择框的 "box-sizing" 属性。它默认为 "border-box",我将其覆盖为 "content-box"。


刚试了一下这个链接(http://jsfiddle.net/hwzd88o5/63/),但结果和我的“无填充测试”在Chrome 50中没有任何区别(因此它没有效果)。你能否做一个JSFiddle展示你的想法是如何工作的呢? - Turnerj

-7

试试这个。对我有用。

 <div id="div">
       <select size=1>
          <option value="0">Option 1</option>
          <option value="1">Option 2</option>
       </select>
  </div>

CSS

 #div option {padding-left: 5px;}

1
不行,在Chrome或Firefox中也不起作用。再看一下我的截图和之前的尝试。 - Turnerj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接