-7

You can use margin-right, for example, to push a next sibling as seen below:

#parent {
  background: tan;
  font-size: 0;
}

#parent * {
  display: inline-block;
  width: 50px;
  height: 50px;
}

#child1 {
  background: teal;
  margin-right: 100px;
}

#child2 {
  background: olive;
}
<div id="parent">
  <div id="child1"></div>
  <div id="child2"></div>
</div>

I know there is no previous sibling selector in CSS. However, I wonder if there's a workaround so #child2 can pull #child1 to a distance of say, 20px. Here's a before-after screenshot:

enter image description here

Note: I don't want to give a margin value to #child1 or alter the HTML. The effect should be achieved using #child2 only.

  • It depends on directions. if you are using `rtl` you may move `child1` – Abhishek Pandey Mar 31 '17 at 08:31
  • What exactly do you mean by pull? margin-left:20px; can be added to #child1 to make it closer to #child2 by 20px. – UIPassion Mar 31 '17 at 10:44
  • 1
    There's no *previous sibling* selector in CSS. But there is a clean and valid way to simulate that behavior with CSS: http://stackoverflow.com/a/36118012/3597276 – Michael Benjamin Mar 31 '17 at 18:03
  • @Michael_B: Please post this as an answer and I'll accept it. Thanks! –  Apr 02 '17 at 18:49
  • 1
    Hi @Mike, I'm just not entirely clear on the overall objective. What exactly do you mean by *pull `.child1`*? Can you post an image? – Michael Benjamin Apr 02 '17 at 20:31
  • 1
    @Michael_B: Sure! Here's a before-after screenshot. –  Apr 03 '17 at 03:32
  • 1
    @AbhishekPandey: Would you mind providing a demo? –  Apr 03 '17 at 05:15
  • 1
    @Mike I don't understand the question. In the first example image `#child2` is located where it is because of the 100px margin-right, but in the second image it has remained where it is, but `#child1` is closer... – JustCarty Apr 04 '17 at 15:46

5 Answers5

1

This code works for me, it doesn't touch #child1 but #parent. Changed to classes instead of ids just to show the same code works for all.

.parent {
  background: tan;
  font-size: 0;
  display: flex;
}

.parent * {
  display: inline-block;
  width: 50px;
  height: 50px;
}

.child1 {
  background: teal;
  margin-right: 100px;
}

.child2 {
  background: olive;
}

.child3 {
  background: red;
}

.parent > div:only-child {
  margin-right:100px;
  margin-left:0px;
}

.parent > div {
  margin-right:20px;
}

.parent > div:first-child:not(:last-child) {
  margin-left:60px;
}
<div class="parent">
  <div class="child1"></div>
  <div class="child2"></div>
  <div class="child3"></div>
</div>
<br>
<div class="parent">
  <div class="child1"></div>
  <div class="child2"></div>
</div>
<br>
<div class="parent">
  <div class="child1"></div>
</div>
0

There is no previous sibling selector using pure CSS. The possible workaround is using CSS flexbox.

First, set display property as flex to the #parent element. reverse the order of displaying child elements

<div id="child2"></div>
<div id="child1"></div> 

We can correct this visually by setting

order:-1 to #child1.

Then we will address the #child1 by using

#parent>div:first-child+div

This means the next div after the first div, ie, #child1. Then set the styles.

#parent>div:first-child+div {
margin-right: 20px;
margin-left: 80px;
}

#parent {
  background: tan;
  display: flex;
}

#parent * {
  width: 50px;
  height: 50px;
}

#child1 {
  background: teal;
  order: -1;
}

#child2 {
  background: olive;
}

#parent>div:first-child+div {
  margin-right: 20px;
  margin-left: 80px;
}
<div id="parent">
  <div id="child2"></div>
  <div id="child1"></div>
</div>

For better understandability, hover the #child2 then you can see the color change of its previous sibling.

#child2:hover+div {
background: brown;
}

#parent {
  background: tan;
  display: flex;
}

#parent * {
  width: 50px;
  height: 50px;
}

#child1 {
  background: teal;
  order: -1;
}

#child2 {
  background: olive;
}

#parent>div:first-child+div {
  margin-right: 20px;
  margin-left: 80px;
}

#child2:hover+div {
  background: brown;
}
<div id="parent">
  <div id="child2"></div>
  <div id="child1"></div>
</div>
Geethu Jose
  • 1,953
  • 2
  • 14
  • 30
  • 1
    I'm looking for a CSS-only solution without touching the HTML. –  Apr 04 '17 at 06:04
  • @Mike What you mean by without touching HTML ? – Sagar V Apr 04 '17 at 06:11
  • 1
    @Mike, We just reverse the order of child elements and reset that using CSS. So visually they look the same. – Geethu Jose Apr 04 '17 at 06:14
  • Please run the code snippet. Hover child2 and you will see the change on its previous sibling. – Geethu Jose Apr 04 '17 at 06:27
  • 1
    @Mike Pure CSS solution is not possible AFAIK – Geethu Jose Apr 04 '17 at 09:47
  • @GeethuJose I am not the DV. But it seems like you added irrelevant codes ( the hover). Is this your own code or taken from somewhere else? – Sagar V Apr 04 '17 at 10:13
  • 1
    I added the hover code to show, how the previous sibling is selected – Geethu Jose Apr 04 '17 at 10:34
  • Agreed. But the first priority is to answer the question only. Then, for illustration, you can add something like, _The working is..._ and explain then add _to verify this_ or something and then you can do the rest. But a fresh code for the OP should be recommended. – Sagar V Apr 04 '17 at 17:56
  • @SagarV: Thanks for your suggestion. I have edited my answer accordingly. – Geethu Jose Apr 05 '17 at 04:06
  • @GeethuJose: "reverse the order of displaying child elements" Thanks for the answer, but there's a misunderstanding: when you do that, `#child1` becomes the second child , and that's why I asked you not to disorder them. –  Apr 05 '17 at 06:11
  • @Mike: To get the desired result, you have to reverse the order of children in HTML and then reset that in CSS. As I told you pure CSS solution is not possible. – Geethu Jose Apr 05 '17 at 06:25
0

I am not sure whether this is what the OP is asking, but the following code, pulls the first child only when the second child exists, so in a sense, the second child pulls the first one :)

#parent > div:first-child:nth-last-child(2) {
    margin-left:60px;
    margin-right:20px;
}

Here is a working fiddle: https://jsfiddle.net/06urn796/

Removing the second child, leaves the first one intact: https://jsfiddle.net/06urn796/1/

Super User
  • 9,448
  • 3
  • 31
  • 47
scooterlord
  • 15,124
  • 11
  • 49
  • 68
0

According to your replies on the given answers your question should have been:

Can you 'pull the previous sibling element' by using CSS (only), and without changing the HTML?

The answer to that question is as simple as unsatisfying:

No, there is not.

Not even when you change the reading direction. I am sorry.

Mr. Hugo
  • 11,887
  • 3
  • 42
  • 60
-1

#parent {
  background: tan;
  font-size: 0;
}

#parent * {
  display: inline-block;
  width: 50px;
  height: 50px;
}
#parent div{
  margin: 0px 20px;
}

#child1 {
  background: teal;
}

#child2 {
  background: olive;
}
<div id="parent">
  <div id="child1"></div>
  <div id="child2"></div>
</div>