使用 :focus 设置外部 div 的样式?

Posted

技术标签:

【中文标题】使用 :focus 设置外部 div 的样式?【英文标题】:Using :focus to style outer 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 会抢回焦点。 【参考方案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.

参考资料:

getElementsByTagName(). onfocusonblurparentNodetagNametoString()toLowerCase()stylefocus()blur()parent()css()

【讨论】:

+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 库。

【讨论】:

以上是关于使用 :focus 设置外部 div 的样式?的主要内容,如果未能解决你的问题,请参考以下文章

js外部样式如何导入

单击外部时如何关闭Android对话框(使用FLAG_NOT_FOCUSABLE)

HTML+CSS:三种css的引入方式,内链式嵌入式外部式

如何在没有外部 css 文件的情况下将 div 元素居中

使用自定义样式将外部元素拖放到summernote编辑器

input 去掉点击后出现的边框