问题 CSS ::满足要素的焦点


如果您有以下HTML:

<div contenteditable="true">
  <p>The first paragraph</p>
  <p>The second paragraph</p>
</div>

有没有办法设置正在编辑的段落与其他段落的不同 div 那是 contenteditable

div > p:focus { border: 1px solid red }

不会应用于正在编辑的段落。

这是一个 的jsfiddle 你可以玩。

我该如何设计风格 正在编辑的段落 (该 <p>-tag)不同?

我更喜欢仅使用CSS的解决方案,但也许我必须使用JavaScript。

编辑:

因为我们找不到纯CSS解决方案(并使用 :hover 对我来说不是一个真正的解决方案)我现在正在寻找设置属性的一些JavaScript行 class="focus" 在正在编辑的节点上。


3740
2018-05-30 09:40


起源

请给我一个提示,告诉我如何改进我的问题。 - pvorb
嘎,我几乎让它工作 - jsfiddle.net/PPNE2/7,当它未被选中时,似乎无法移除边框。 - lifetimes
@Zenith很好的方法 - pvorb
你只需要放 contenteditable="true" 每一个 p - Optimus Prime
@optim见下面的答案。 - pvorb


答案:


我想我找到了解决方案。

使用以下代码段,您可以在选择更改时获取当前插入符号位置的父元素。

var selectedElement = null;
function setFocus(e) {
  if (selectedElement)
    selectedElement.style.outline = 'none';

  selectedElement = window.getSelection().focusNode.parentNode;
  // walk up the DOM tree until the parent node is contentEditable
  while (selectedElement.parentNode.contentEditable != 'true') {
    selectedElement = selectedElement.parentNode;
  }
  selectedElement.style.outline = '1px solid #f00';
};
document.onkeyup = setFocus;
document.onmouseup = setFocus;

我在这里改变了 outline 手动属性,但你当然可以添加一个类属性并通过CSS设置样式。

您仍然需要手动检查是否 selectedElement 是我们的孩子 <div> 随着 contenteditable 属性。但我认为你可以得到基本的想法。

这是 更新了JSFiddle

编辑:我更新了代码以及JSFiddle,使其可以在Firefox和Internet Explorer 9+中使用。不幸的是,这些浏览器没有 onselectionchange 事件处理程序,所以我不得不使用 onkeyup 和 onmouseup


9
2018-05-30 15:46



这在Firefox或IE10中不起作用(可能也是所有旧的IE)。 - lifetimes
谢谢你的提示。我来看看吧。 - pvorb
@Zenith我修复了代码,因此它适用于Firefox和IE9 +。 - pvorb
所以你做到了! +1它有效! - lifetimes
+1。这几乎就是我所建议的。有一点是,如果用户将某些文本设为粗体,然后将插入符号放在粗体文本中,则会失败,因为 window.getSelection().focusNode.parentNode现在将是大胆的元素而不是段落。我建议迭代 parentNode直到你打了一个 <p> 元素代替;看到 stackoverflow.com/a/4642894/96100。另一件小事:选择可以在没有键或鼠标事件触发的情况下改变(例如,通过浏览器菜单中的选择所有选项),因此您可能需要一个轮询解决方案作为后备。 - Tim Down


有趣的问题。如果它可行,我建议将contenteditable属性移动到 p他们自己: http://codepen.io/pageaffairs/pen/FHKAC

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">

<style media="all">

div > p:focus {outline: 1px solid red; }

</style>

</head>
<body>

<div>
    <p contenteditable="true">The first paragraph</p>
    <p contenteditable="true">The second paragraph</p>
</div>

</body>
</html>

编辑:这是另一个版本,导致para返回生成para而不是div: http://codepen.io/pageaffairs/pen/dbyIa

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">

<style media="all">

div:focus {outline: none;}
div > p:focus, div > p:hover {outline: 1px solid red; }

</style>

</head>
<body>

<div contenteditable="true">
    <p contenteditable="true">The first paragraph</p>
    <p contenteditable="true">The second paragraph</p>
</div>

</body>
</html>

3
2018-05-30 09:56



这通常是我想要的,但它带来了一些副作用:假设我在最后一段末尾点击返回。在我的版本中,添加了一个新段落。在您的版本中,它将插入一个 <div> 在那里面 <p>。奇怪的行为... :( - pvorb
杰西,这很奇怪。好吧,我添加了另一个似乎有效的例子。唯一的问题是,我不得不添加悬停样式以使焦点集中在段落上。去搞清楚。 - ralph.m
对不起,但悬停状态对我来说不是一个选项,因为即使你没有使用鼠标我想指出你正在编辑的段落。也许我必须解决这个问题 <div> 插入问题或我可以通过JavaScript找到当前光标位置周围的元素。 - pvorb
我更新了这个问题,因此欢迎使用JavaScript解决方案。 - pvorb


jsFiddle在这里。

以下是不完美的,因为您的鼠标需要与所选段落位于同一区域(以保持 :hover 参数是真的),但通常情况下这应该是好的 - 如果你想保留你的标记,那么你将获得最好的结果:

CSS:

div[contenteditable="true"]:focus > p:hover {
   border: 2px solid red;
}

HTML:

<div contenteditable="true">
   <p>The first paragraph</p>
   <p>The second paragraph</p>
</div>

jsFiddle在这里。

如果您能够更改标记,则可以使用以下简化选择器:

CSS:

p[contenteditable="true"]:focus {
   border: 2px solid red;
}

HTML:

<div>
   <p contenteditable="true">The first paragraph</p>
   <p contenteditable="true">The second paragraph</p>
</div>

1
2018-05-30 10:21



嗯,不过在一个段落周围有内联跨度会更好 - 至少从验证的角度来看。 - ralph.m
第二个是我在第一个回复中发布的,但它有一个问题,当你按Enter / Return时,它会创建一个新的 <div> 而不是一个新的 <p>因此我的第二次尝试。 - ralph.m
@ ralph.m真的吗?它不在这里 - jsfiddle.net/PPNE2/16 - lifetimes
@Zenith嗯,它至少在Chrome中有用。在Firefox中它创建了一个 <br> 这很好。 - pvorb