user3390639 user3390639 - 2 months ago 6
CSS Question

Selector for the margin-top and margin-bottom of an element

I want to have different :hover cursor in an element, lets say pointer on the element, n-resize for the margin-top, and s-resize for the margin bottom. I know I can make a different div before and after the span element to have the selector that. The problem is, the tree HTML is auto-generated from a JS library (fancytree, a tree library), I'm afraid if I manually insert another element before and after the span, the functionality will breaks. Any help is appreciated.

Here is the following image explaining the situation.

enter image description here

Here's my LESS code as suggested by one of the comment, it doesn't work.

span.fancytree-node {
/* See #117 */
display: inherit; // #117, resolves to 'display: list-item;' for standard trees
width: 100%;
margin-top: @fancy-node-v-spacing;
margin-bottom: @fancy-node-v-bottom-spacing;
min-height: @fancy-line-height;
cursor: pointer;
:before {
cursor: n-resize;
}
:after {
cursor: s-resize;
}
}


To make it more clear, I need the margin, I can't add another element above and below the element, because that margin is used by my JS library to detect drag n drop placement.

Answer
  • Make the parent of the :before and :after pseudo-elements position: relative
  • Make the two pseudo-elements position: absolute and position with top / right / bottom and left.
    • Using both left and right will stretch the element between the left and right edges of the parent.
  • Use a negative top or bottom value that is equal to the value of the margins so that the pseudo-elements are placed over the margin of their parent. Their heights will be the same as well.

Example

Note: It's possible the pseudo-elements may interfere with the JS drag and drop. That's not possible to test with what we can re-create from the question. There may be a better solution that involves changing the pointers with JS.

div {
  margin-top: 10px;
  margin-bottom: 10px;
  min-height: 20px;
  cursor: pointer;
  position: relative;
  background: pink;
}
div:before,
div:after {
  cursor: n-resize;
  content: '';/*Needed to show the pseudo-elements*/
  position: absolute;
  top: -10px;/*Same as margin*/
  left: 0;
  right: 0;
  height: 10px;/*Same as margin*/
}
div:after {
  cursor: s-resize;
  top: initial;
  bottom: -10px;/*Same as margin*/
}
<div>Item</div>