【问题标题】:Using :focus to style outer div?使用 :focus 设置外部 div 的样式?
【发布时间】:2011-12-14 03:30:51
【问题描述】:

当我开始在 textarea 中编写文本时,我希望带有类框的外部 div 的边框变为实心而不是虚线,但不知何故 :focus 在这种情况下不适用。如果它可以与 :active 一起使用,为什么它不能与 :focus 一起使用?

有什么想法吗?

(注意。我希望 DIV 的边框变为实心,而不是 textareas)

div.box
{
    width: 300px;
    height: 300px;
    border: thin dashed black;
}

div.box:focus{
    border: thin solid black;
}

<div class="box">
    <textarea rows="10" cols="25"></textarea>
</div>

【问题讨论】:

  • 它不适用于焦点,因为 DIV 没有焦点,只有 TextArea 有。我会想象一个 DIV 无论如何都不能有焦点,因为它是一个不可选择的元素
  • 您需要使用 JavaScript 来实现这一点;因为虽然 div 可以集中注意力,但如果单击它,textarea 会立即将其收回。 JS Fiddle demo;在textarea 之外单击将更改div 的边框,但激活textarea 会抢回焦点。

标签: css focus stylesheet


【解决方案1】:

其他发帖者已经解释了:focus伪类不足的原因,但终于有了基于CSS的标准解决方案。

CSS Selectors Level 4 定义了一个新的伪类:

:focus-within

来自MDN

:focus-within CSS 伪类匹配 :focus 的任何元素 伪类匹配或具有:focus 的后代 伪类匹配。 (这包括影子树的后代。)

所以现在有了:focus-within 伪类 - 当textarea 被点击时,外部 div 的样式变得微不足道了。

.box:focus-within {
    border: thin solid black;
}

.box {
    width: 300px;
    height: 300px;
    border: 5px dashed red;
}

.box:focus-within {
    border: 5px solid green;
}
<p>The outer box border changes when the textarea gets focus.</p>
<div class="box">
    <textarea rows="10" cols="25"></textarea>
</div>

Codepen demo

注意: Browser Support:Chrome (60+)、Firefox 和 Safari

【讨论】:

  • 哇,没想到有这个,这是一个非常有用的选择器修饰符!
  • 惊人的答案:)
  • 迄今为止最简单和最好的答案。也不知道这个选择器存在。根据我的测试,在 Mozilla 和 Chrome 中工作。
  • 太棒了,太棒了
  • 只想提一下tabindex还是需要的,当有静态元素(div、span等)混合在一起的时候,还有外层div里面的input元素,并且需要焦点轮廓即使单击内部静态元素之一。
【解决方案2】:

如果设置tabindex 属性,DIV 元素可以获得焦点。这是工作示例。

#focus-example > .extra {
  display: none;
}
#focus-example:focus > .extra {
  display: block;
}
<div id="focus-example" tabindex="0">
  <div>Focus me!</div>
  <div class="extra">Hooray!</div>
</div>

有关focusblur的更多信息,您可以查看this article

更新: 这是另一个使用focus 创建menu 的示例。

#toggleMenu:focus {
  outline: none;
}
button:focus + .menu {
  display: block;
}
.menu {
  display: none;
}
.menu:focus {
  display: none;
}
<div id="toggleMenu" tabindex="0">
  <button type="button">Menu</button>
  <ul class="menu" tabindex="1">
    <li>Home</li>
    <li>About Me</li>
    <li>Contacts</li>
  </ul>
</div>

【讨论】:

  • @NamanSood 我已将代码包含在我的答案中。看看吧。
  • 这是跨浏览器破解吗?
  • @jayarjo 它对我有用。用于 Ubuntu 的 Mozilla Firefox,版本。 49.0
  • 当你没有输入时它可以工作。如果单击 div 中的非输入 dom,它可以工作。如果点击 div 中的输入 dom,输入 dom 将捕获您的焦点事件并停止弹出。
【解决方案3】:

虽然这不能单独使用 CSS/HTML 来实现,但可以使用 JavaScript 来实现(无需库):

var textareas = document.getElementsByTagName('textarea');

for (i=0;i<textareas.length;i++){
    // you can omit the 'if' if you want to style the parent node regardless of its
    // element type
    if (textareas[i].parentNode.tagName.toString().toLowerCase() == 'div') {
        textareas[i].onfocus = function(){
            this.parentNode.style.borderStyle = 'solid';
        }
        textareas[i].onblur = function(){
            this.parentNode.style.borderStyle = 'dashed';
        }
    }
}

JS Fiddle demo.

顺便说一句,使用 jQuery 之类的库,上面的内容可以浓缩为:

$('textarea').focus(
    function(){
        $(this).parent('div').css('border-style','solid');
    }).blur(
    function(){
        $(this).parent('div').css('border-style','dashed');
    });

JS Fiddle demo.

参考资料:

【讨论】:

  • +1 以获得详细答案(尤其是不需要 jQuery 的答案)
  • 引入 :focus-within 伪元素不再是最有效的答案!
  • 这是一个很好的答案,我认为仍然有效,因为 :focus-within 目前仍是一个工作草案。这正是我所需要的。谢谢。
【解决方案4】:

现在可以通过 css 方法 :focus-within 来实现这一点,如本文所示:http://www.scottohara.me/blog/2017/05/14/focus-within.html

/*
  A normal (though ugly) focus
  pseudo-class.  Any element that
  can receive focus within the
  .my-element parent will receive
  a yellow background.
*/
.my-element *:focus {
  background: yellow !important;
  color: #000;
}

/*
  The :focus-within pseudo-class
  will NOT style the elements within
  the .my-element selector, like the
  normal :focus above, but will
  style the .my-element container
  when its focusable children
  receive focus.
*/
.my-element:focus-within {
  outline: 3px solid #333;
}
<div class="my-element">
  <p>A paragraph</p>
  <p>
    <a href="http://scottohara.me">
      My Website
    </a>
  </p>

  <label for="wut_email">
    Your email:
  </label>
  <input type="email" id="wut_email" />
</div>

【讨论】:

    【解决方案5】:

    简单使用 JQuery。

    $(document).ready(function() {
      $("div .FormRow").focusin(function() {
        $(this).css("background-color", "#FFFFCC");
        $(this).css("border", "3px solid #555");
      });
      $("div .FormRow").focusout(function() {
        $(this).css("background-color", "#FFFFFF");
        $(this).css("border", "0px solid #555");
      });
    });
        .FormRow {
          padding: 10px;
        }
    <html>
    
    <head>
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    </head>
    
    <body>
      <div style="border: 0px solid black;padding:10px;">
        <div class="FormRow">
          First Name:
          <input type="text">
          <br>
        </div>
        <div class="FormRow">
          Last Name:
          <input type="text">
        </div>
      </div>
    
      <ul>
        <li><strong><em>Click an input field to get focus.</em></strong>
        </li>
        <li><strong><em>Click outside an input field to lose focus.</em></strong>
        </li>
      </ul>
    </body>
    
    </html>

    【讨论】:

    • 更简单的是,不要使用 jquery,有一个很好的例子,解决方案,@DavidThomas ... 大约加载 jquery 文件有什么意义? 77-94kB 对于这样的东西,还有更多......
    • @nelek,如果你仍然使用 jQuery,这是一个很好的解决方案,也更健壮(跨浏览器,无需永远在你甚至无法访问的浏览器上进行调试!)
    【解决方案6】:

    根据the spec

    :focus 伪类在元素具有焦点时应用(接受键盘事件或其他形式的文本输入)。

    &lt;div&gt; 不接受输入,所以它不能有:focus。此外,CSS 不允许您基于针对其后代的元素设置样式。因此,除非您愿意使用 JavaScript,否则您无法真正做到这一点。

    【讨论】:

    • 请注意,如果您设置contenteditable="true" 属性,&lt;div&gt; 可以获得焦点。但在那种情况下,这可能不是答案。
    【解决方案7】:

    焦点内

    .box:focus-within {
      background: cyan;
    }
    

    read more here

    【讨论】:

      【解决方案8】:

      您可以在 div 标签之间使用制表符。只需将选项卡索引添加到 div。最好使用 jQuery 和 CSS 类来解决这个问题。这是在 IE、Firefox 和 Chrome 中测试的工作示例(最新版本...未测试旧版本)。

      <html>
          <head>
              <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
              <script type="text/javascript">
                  var divParentIdFocus;
                  var divParentIdUnfocus = null;
      
                  $(document).ready(function() {              
      
                          $("div").focus(function() {
                              //$(this).attr("class", "highlight");
                              var curDivId = $(this).attr("id");
      
                              // This Check needs to be performed when/if div regains focus
                              // from child element.
                              if (divParentIdFocus != curDivId){
                                  divParentIdUnfocus = divParentIdFocus;
                                  divParentIdFocus = curDivId;
                                  refreshHighlight();
                              }
      
                              divParentIdFocus = curDivId;
                          });
      
      
                          $("textarea").focus(function(){
                              var curDivId = $(this).closest("div").attr("id");
      
                              if(divParentIdFocus != curDivId){
                                  divParentIdUnfocus = divParentIdFocus;
                                  divParentIdFocus = curDivId;
                                  refreshHighlight();
                              }
                          });
      
                          $("#div1").focus();
                  });
      
                  function refreshHighlight()
                  {
                      if(divParentIdUnfocus != null){
                          $("#" +divParentIdUnfocus).attr("class", "noHighlight");
                          divParentIdUnfocus = null;
                      }
      
                      $("#" + divParentIdFocus).attr("class", "highlight");
                  }
              </script>
              <style type="text/css">
                  .highlight{
                      background-color:blue;
                      border: 3px solid black;
                      font-weight:bold;
                      color: white;
                  }
                  .noHighlight{           
                  }
                  div, h1,textarea, select { outline: none; }
      
              </style>
          <head>
          <body>
              <div id = "div1" tabindex="100">
                  <h1>Div 1</h1> <br />
                  <textarea rows="2" cols="25" tabindex="101">~Your Text Here~</textarea> <br />
                  <textarea rows="2" cols="25" tabindex="102">~Your Text Here~</textarea> <br />
                  <textarea rows="2" cols="25" tabindex="103">~Your Text Here~</textarea> <br />
                  <textarea rows="2" cols="25" tabindex="104">~Your Text Here~</textarea> <br />
              </div>
              <div id = "div2" tabindex="200">
                  <h1>Div 2</h1> <br />
                  <textarea rows="2" cols="25" tabindex="201">~Your Text Here~</textarea> <br />
                  <textarea rows="2" cols="25" tabindex="202">~Your Text Here~</textarea> <br />
                  <textarea rows="2" cols="25" tabindex="203">~Your Text Here~</textarea> <br />
                  <textarea rows="2" cols="25" tabindex="204">~Your Text Here~</textarea> <br />
              </div>
              <div id = "div3" tabindex="300">
                  <h1>Div 3</h1> <br />
                  <textarea rows="2" cols="25" tabindex="301">~Your Text Here~</textarea> <br />
                  <textarea rows="2" cols="25" tabindex="302">~Your Text Here~</textarea> <br />
                  <textarea rows="2" cols="25" tabindex="303">~Your Text Here~</textarea> <br />
                  <textarea rows="2" cols="25" tabindex="304">~Your Text Here~</textarea> <br />
              </div>
              <div id = "div4" tabindex="400">
                  <h1>Div 4</h1> <br />
                  <textarea rows="2" cols="25" tabindex="401">~Your Text Here~</textarea> <br />
                  <textarea rows="2" cols="25" tabindex="402">~Your Text Here~</textarea> <br />
                  <textarea rows="2" cols="25" tabindex="403">~Your Text Here~</textarea> <br />
                  <textarea rows="2" cols="25" tabindex="404">~Your Text Here~</textarea> <br />
              </div>      
          </body>
      </html>
      

      【讨论】:

        【解决方案9】:

        据我所知,您必须使用 javascript 向上移动 dom。

        类似这样的:

        $("textarea:focus").parent().attr("border", "thin solid black");
        

        您还需要加载 jQuery 库。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-10-11
          • 2018-09-22
          • 1970-01-01
          • 2013-08-28
          • 2014-02-10
          • 1970-01-01
          相关资源
          最近更新 更多