CSS:当子元素获得焦点时更改父元素

169

假设你有这样的东西:

<div class="parent">
    <input class="childInput" type="text" />
    <div class="sibling"></div>
</div>
我想在子元素获取焦点时改变父元素/兄弟元素的外观。是否有任何 CSS 技巧可以实现这样的操作? 编辑: 我的问题原因如下:
我正在创建一个需要可编辑文本字段的 Angular 应用程序。它应该看起来像一个标签,直到被点击为止,此时它应该看起来像一个普通的文本输入框。我使用 :focus 样式来设计文本字段以实现这种效果,但是文本被文本输入框的边界截断了。我还使用了 ng-show、ng-hide、ng-blur、ng-keypress 和 ng-click 来基于失焦、按键和单击之间的转换在标签和文本输入框之间进行切换。这个方法除了一个问题之外都很好:在标签的 ng-click="setEdit(this, $ event)" 更改由 ng-show 和 ng-hide 使用的编辑布尔值为 true 之后,它使用一个 jQuery 调用来 .select() 文本输入框。然而,直到 ng-click 完成时才完成 $digest,所以文本输入框再次失去焦点。由于文本输入框实际上从未获得焦点,因此使用 ng-blur 返回到显示标签是有问题的:用户必须先单击文本输入框,然后再次单击以返回到显示标签。 编辑: 这里是一个示例 plunk,演示了这个问题:http://plnkr.co/edit/synSIP?p=preview

JavaScript不是选项吗? - Andi
1
这不能仅使用CSS完成,你需要使用js。 - Tushar
是的,但我很好奇是否可以通过样式来完成。我会添加一个编辑来解释我的问题原因。 - AaronF
1
仅使用CSS无法完成父级匹配。只有在元素相邻定义元素时,才能进行同级匹配。请参阅https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_selectors - haim770
请查看此链接:https://dev59.com/wm3Xa4cB1Zd3GeqPd2HS,这是同样的问题。 - MickyScion
5个回答

463

现在你可以使用纯CSS来实现这一点,无需JavaScript

新的CSS伪类:focus-within可用于此类情况,并且在人们使用制表符进行导航时有助于辅助功能,这在使用屏幕阅读器时很常见。

.parent:focus-within {
  border: 1px solid #000;
}

:focus-within 伪类匹配自身匹配 :focus 或其后代匹配 :focus 的元素。

我能用吗...

您可以通过访问http://caniuse.com/#search=focus-within来检查哪些浏览器支持此功能。


演示

fieldset {
  padding: 0 24px 24px !important;
}

fieldset legend {
  opacity: 0;
  padding: 0 8px;
  width: auto;
}

fieldset:focus-within {
  border: 1px solid #000;
}

fieldset:focus-within legend {
  opacity: 1;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />

<div class="container">
  <form>
    <fieldset>
      <legend>Parent Element</legend>
      <div class="form-group">
        <label for="name">Name:</label>
        <input class="form-control" id="name" placeholder="Enter name">
      </div>
      <div class="form-group">
        <label for="email">Email:</label>
        <input type="email" class="form-control" id="email" placeholder="Enter email">
      </div>
    </fieldset>
  </form>
</div>


29
真的很棒! - Jamie Carter
6
IE应该被淘汰了。安息吧。 - Mike Aron
哇,我不知道这个伪类,这让我的代码变得更简洁了!谢谢。 - Rachit Kyte.One
这在许多年前是不可能的!活着真好。 - Satbir Kira

3

CSS无法完成这个操作。CSS只能样式化兄弟、子元素,而不能样式化父元素。

你可以使用以下JS代码:

<style>
.parent {background: green}
.focused {background: red;}
</style>
<div class="parent">
    <input class="childInput" type="text" />
    <div class="sibling"></div>
</div>

<script>
$('.parent > *')
    .focus(function() {
        $('.parent').addClass('focused');
    })
    .blur(function() {
        $('.parent').removeClass('focused');
    });
</script>

这段代码会选取所有直接子元素为.parent的元素,如果你聚焦其中一个元素,父元素会添加focused类。当失去聚焦时,此类将被移除。

http://jsfiddle.net/C4bZ6/


谢谢你的回答。我添加了一个编辑,关于我提出问题的原因:我想在焦点/失焦时在标签和输入之间切换,并且在Angular中做这个操作遇到了一些问题。 - AaronF
1
这不是纯粹的JS,而是使用了jQuery。 - MrVanilla
DV - 不是 JS, OP 也没有要求 jQuery。 - TheCarver

1
你可以使用纯CSS使文本输入框在未获得焦点时看起来不像是文本输入框。

http://jsfiddle.net/michaelburtonray/C4bZ6/13/

input[type="text"] {
    border-color: transparent;
    transition-duration: 600ms;
    cursor: pointer;
    outline-style: none;
    text-overflow: ellipsis;
}

input[type="text"]:focus {
    border-color: initial;
    cursor: auto;
    transition-duration: 300ms;
}

谢谢。我实际上尝试过了,但遇到了一些问题:“...我基于:focus样式化了文本字段以实现这种效果,但是文本被文本输入的边界截断了...”。显示省略号肯定比剪切好,但如果可能的话,我想看到整个东西。如果您感兴趣,我刚刚提出的一个相关问题在这里:http://stackoverflow.com/questions/24289266/select-input-shown-with-ng-show?noredirect=1#comment37532406_24289266。 - AaronF

1

1
确实很有用。不幸的是,我们的客户群需要使用不符合HTML5标准的浏览器。 - AaronF

0
你可以为 focus-within 和 not(focus-within) 进行样式设置,就像这样(无需使用 JavaScript => 更易访问且速度更快):
        .myform:not(:focus-within) button[type="submit"] {
            display: none;
        }

        .myform:focus-within button[type="submit"] {
            display: block;
        }

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