【问题标题】:How to style radio buttons differently if they fit in a single row?如果它们适合单行,如何以不同的方式设置单选按钮?
【发布时间】:2015-07-17 21:59:49
【问题描述】:

PLAYGROUND HERE

如果单选按钮可以放在一行中,我想以不同的方式设置它们的样式。例如:

第一个容器没有足够的空间来容纳单行中的所有单选按钮。因此,它们垂直显示为普通的单选按钮。

第二个容器有足够的空间。因此,单选按钮显示为按钮。

是否有可能仅使用 CSS 来实现此行为?

如果没有,欢迎使用 Javascript “hack”。

PLAYGROUND HERE


HTML

<div class="container radio">
  <div>
    <input id="a1" type="radio" name="radio">
    <label for="a1">Yes,</label>
  </div>
  <div>
    <input id="a2" type="radio" name="radio">
    <label for="a2">it</label>
  </div>
  <div>
    <input id="a3" type="radio" name="radio">
    <label for="a3">is</label>
  </div>
  <div>
    <input id="a4" type="radio" name="radio">
    <label for="a4">possible</label>
  </div>
  <div>
    <input id="a5" type="radio" name="radio">
    <label for="a5">to</label>
  </div>
  <div>
    <input id="a6" type="radio" name="radio">
    <label for="a6">achieve</label>
  </div>
  <div>
    <input id="a7" type="radio" name="radio">
    <label for="a7">this</label>
  </div>
</div>
<div class="container buttons">
  <div>
    <input id="b1" type="radio" name="buttons">
    <label for="b1">Yes,</label>
  </div>
  <div>
    <input id="b2" type="radio" name="buttons">
    <label for="b2">it</label>
  </div>
  <div>
    <input id="b3" type="radio" name="buttons">
    <label for="b3">is</label>
  </div>
  <div>
    <input id="b4" type="radio" name="buttons">
    <label for="b4">possible</label>
  </div>
</div>

CSS (LESS)

.container {
  display: flex;
  width: 220px;
  padding: 20px;
  margin-top: 20px;
  border: 1px solid black;

  &.radio {
    flex-direction: column;
  }

  &.buttons {
    flex-direction: row;

    > div {
      input {
        display: none;

        &:checked + label {
          background-color: #ADFFFE;
        }
      }

      label {
        padding: 5px 10px;
        margin: 0 1px;
        background-color: #ccc;
      }
    }
  }
}

【问题讨论】:

  • 虽然非常感谢 JS Bin 复制的链接,但您必须在问题本身中发布相关代码以防止链接腐烂。如果您的目标是提供演示(再次感谢:非常感谢!),那么您可以简单地使用 Stack Overflow 的“Stack Snippets”功能。

标签: javascript html css flexbox


【解决方案1】:

在 CSS 中不可能,但它不需要太多 JavaScript。

在 CSS 中,将 flex-shrink: 0 添加到 &gt; div。这将防止.container 的孩子缩小到小于他们的范围。

在 JavaScript 中:

  1. 应用buttons 类。
  2. 使用Element.getBoundingClientRect 确定.container 的最后一个孩子是否在.container 的范围之外。如果是这样,请切换到 radio 类。 (您还需要考虑正确的填充。感谢@Moob 指出这一点。)

Javascript

var container = document.querySelector('.container'),
    lastChild= document.querySelector('.container > :last-child'),
    paddingRight= parseInt(window.getComputedStyle(container, null).getPropertyValue('padding-right')),
    timer;

window.onresize = function() {
  clearTimeout(timer);
  timer= setTimeout(function() {
    container.classList.remove('radio');
    container.classList.add('buttons');
    if (container.getBoundingClientRect().right-paddingRight <
        lastChild.getBoundingClientRect().right) {
      container.classList.add('radio');
      container.classList.remove('buttons');
    }
  });
}

Updated JSBin

【讨论】:

  • 很好的解决方案。不知道flex-shrink(在我的大部分工作中仍然避免使用弹性盒)。我用它来改进我自己的答案。谢谢。
  • @Rick 不错!每次调整窗口大小时,我都尝试运行您的 JS,但我看到了奇怪的闪烁效果:jsbin.com/garuvexaha/1/edit?html,js,output 知道有什么问题吗?
  • onresize 在调整大小时不断运行。最好加个超时。请参阅jsbin.com/cibudaforu/1/edit?html,js,output 的更新
  • @RickHitchcock 现在没有闪烁,但我仍然可以看到不良行为:dl.dropbox.com/u/1893981/Screenshots/x-10.png(应该是单选按钮)
  • 我已从 scrollWidth 切换到 getBoundingClientRect。这样就解决了问题。
【解决方案2】:

您只需使用 css 即可实现此目的,无需编写脚本。

HTML:您必须将输入放在包含文本的标签内。

<div>
<label for="a1">
    <input id="a1" type="radio" name="radio">Yes,
</label>  </div>

CSS:在 CSS 中,我们必须隐藏单选按钮,以便只有文本可见。当用户点击文本时,它实际上是点击了单选按钮。

div lable input#a1{
   display:none;
}

【讨论】:

    【解决方案3】:

    如果需要的话,测试宽度是否有效,然后删除单选按钮图标并替换为图形或形状?

    .checkbox {
        display:none;
    }
    
    .label {
        display: inline-block;
        height: 20px;
        background: url('picture.png');
    }
    

    这可能不是那么简单,但我将它用于复选框,它似乎在这种情况下工作。

    【讨论】:

      【解决方案4】:

      试试下面的例子............ ------------HTML------------

      <html>
      <head>
       <link rel="stylesheet" href="style.css" type="text/css" /> 
      </head>
      <body>
          <div class="table-row">
              <div class="col">
                      <input type="Radio">This
                  </div>
                  <div class="col" style="padding-top: 2px;">
                      <input type="Radio">Is
                  </div>  
      
                  <div class="col">
                      <input type="Radio">Simply
                  </div>
                  <div class="col" style="padding-top: 2px;">
                      <input type="Radio">Possible
                  </div>  
      
              </div>  
      </body>
      </html>
      

      -------CSS-------------

      .table-row{  
           display:table-row;     
           /* text-align: center; */
      }
      .col{
          display:table-cell;
          /* border: 1px solid #CCC; */
      }
      

      【讨论】:

        【解决方案5】:

        我想不出只有 CSS 的解决方案,但您可以使用 JS 来测试项目是否可以排成一行并相应地应用“收音机”或“按钮”类名:

        请原谅我粗糙的 JS - 它不优雅且仅适用于现代浏览器,但你明白了:

        var containers = document.querySelectorAll(".container"),
        test = function(){
            for (i = 0; i < containers.length; ++i) {
              var container = containers[i],
                  divs = container.querySelectorAll("div"),
                  iw = 0;
              container.classList.remove("radio");
              container.classList.add("buttons");
              //get the sum width of the div
              for (d = 0; d < divs.length; ++d) {
                iw+=divs[d].offsetWidth;
              }
              var style = window.getComputedStyle(container, null);
              var ow = parseInt(style.getPropertyValue("width"));
              if(ow<=iw){
                  container.classList.add("radio");
                  container.classList.remove("buttons");            
              }
            }
        };
        
        window.onresize = function(event) {
            test();
        };
        test();
        

        http://jsbin.com/zofixakama/3/edit?html,css,js,output
        (调整窗口/面板大小以查看效果)

        更新:如果将.container div {flex-shrink:0;} 添加到样式中,JS 可以更简单,因为我们不必测量 div 的组合宽度(感谢@rick-hitchcock)。不过,虽然代码更加优雅,但并没有考虑到容器的padding

        见:http://jsbin.com/zofixakama/5/edit?html,css,js,output

        【讨论】:

        • @humble.rumble.6x3 同意,更新版本 (v5) 没有考虑填充,但是代码示例(和 v3 的链接)确实。我已经更新了我的答案以反映这一点。谢谢。
        【解决方案6】:

        如果我理解您的要求正确,您可以将您的 flex-direction 部分更改为 row 而不是 column。这将使它们在框内对齐。

        您必须进行更多样式设置才能使标签以您想要的方式正确显示,但这应该为您将它们放在行中。 I've updated the playground with my changes.

        【讨论】:

        • 恐怕你误解了这个问题。在我的示例中,有两个容器。其中一个是radio,另一个是buttons。我不想在容器上有这些类。我添加它们仅用于演示目的。问题是如何在不手动添加这些类的情况下创建您在演示中看到的行为。
        • 嗯,好的。我现在知道了。我会相应地更新我的答案
        【解决方案7】:

        只有 CSS 有很好的解决方案,但你必须知道行中元素的最大数量。它基于计数器,而不是实际大小。

        例如,如果您确定可以将 4 个元素排成一行,则无论如何,您都可以使用以下选择器:

        如果金额大于或等于4:

        div:nth-last-child(-n+5):first-child,
        div:nth-last-child(-n+5):first-child ~ div {
            }
        

        如果数量大于 4:

        div:nth-last-child(n+5),
        div:nth-last-child(n+5) ~ div {
        }
        

        试试这个:http://jsbin.com/fozeromezi/2/edit(只需删除/添加 div)

        【讨论】:

        • ...但如果元素的宽度未知或不等,我们将无法知道有多少能适合。
        • 视情况而定。您始终可以将“溢出省略号”与“显示内联块”和固定宽度结合使用。这就是为什么我提到这个答案只适用于某些条件,但它是纯 CSS 的。
        猜你喜欢
        • 2014-08-20
        • 2019-03-25
        • 2012-02-24
        • 2011-08-15
        • 2014-09-07
        • 2012-07-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多