0

My question is highly related to this previously answered question. In fact, the solution provided by @harpo in the comments of the top-voted answer was a partial solution for me. However, I've found that it actually doesn't work on some of my elements, in particular, elements that have borders.

Some context: I'm using Bootstrap for my page, and I have a fixed navbar on top, then a page with a load of unstyled divs and .panel divs inside those divs. I have a top padding of 60px on my body which pushes everything down to account for the navbar. However, when I click on a link with an offset (e.g. example.com#div2-1), the top of the div is still covered by the navbar.

Using the solution provided in the linked answer above, I put 60px of negative padding (pulling the element up by 60px) on the :before element, then push it down by 60px again by setting the height to 60px. This creates no visual difference (intentional) but the calculated height of my div is now 60px taller, with the div starting 60px earlier than it should, and the real content starting 60px later. This essentially offsets the content for the navbar again.

However, I've found that on elements that have a border, such as my .panel elements, the border seems to contain everything, and the :before pseudo-element I have no longer has an effect on the calculated height of my div, which means it gets covered by the navbar again.

Here's my code on JSFiddle: http://jsfiddle.net/rszqtw80/3/

If you take a look at the rendered result in any dev tool, you can clearly see that the :before element is properly created and has the right height (60px) for both the outer and inner divs. But for the inner divs, the overall calculated height of the element ends up not including the :before element. Disabling the border with Chrome Dev Tools makes it work for me, so I've deduced that the border is the problem.

So my question: is it possible to get this CSS-based offset to work with my .panel elements without losing the border or having to go back to inserting a tags everywhere? Because quite honestly, without the border, the .panels look quite ugly, and nesting every div in an a tag is also quite ugly.

Thanks in advance!

EDIT: Rewrote my question slightly to hopefully clear up any misunderstandings about my intent. Sorry for my confusing explanation :(

FURTHER EDIT: I've added 3 screenshots that hopefully demonstrates this better than any words can ever hope to do. I would've added it here, but I can't add more than two links due to lack of "reputation".

Community
  • 1
  • 1
southrop
  • 819
  • 10
  • 19
  • 2
    What are you trying to achieve with your :before element? Because right now it's doing nothing because of the margin-top:-60px. – Frederik Witte Oct 20 '14 at 03:40
  • It adds 60px height before my div, which allows me to offset for a fixed header. Specifically, I increase the height of the div by 60px with `margin-top:-60px` and then push everything down by 60px with `height:60px`, which means there is no visual difference. If I don't use this, when I use an anchor offset in my page URL, the anchored element appears at the top of my page, which then gets covered by my header. – southrop Oct 20 '14 at 03:49
  • This can't work, you have to have another mistake somewhere else then. So you want to offset the whole anchor block 60px, right? Not every single anchor block? – Frederik Witte Oct 20 '14 at 03:51
  • No, I want every anchor block to have this invisible offset. It works perfectly fine on elements that don't have a border (take a look at the JSFiddle and check the calculated size). But when an element does have a border, the border seems to contain the size to within the border. The `:before` element is still there, it just has no effect. Disabling the border actually does make it work, hence my question. – southrop Oct 20 '14 at 03:53
  • Please take a look at this fiddle: http://jsfiddle.net/rszqtw80/4/ The solution provided by you CAN NOT work. It's simply impossible, because you collapse your height with your margin to the top of the page, so it doesn't affect anything. – Frederik Witte Oct 20 '14 at 04:05
  • My apologies. I forgot to include that I have a `padding-top: 60px` applied to `body`, which is why it works for me. I have updated my JSFiddle in the post above. Sorry for the confusion there :( – southrop Oct 20 '14 at 04:09
  • This is now your body making your padding :P It is still not the :before element. One more question: You now have Div 1 and Div 2 and anchors inside. Do you want your padding only from Div 1 to Div 2, or for every single anchor? – Frederik Witte Oct 20 '14 at 04:21
  • I think there may be some misunderstanding here. Yes, the `body` has an offset which pushes everything down. However, it also pushes down the positions of my anchors, which means that when I follow a page URL with a `#offset` (e.g. example.com/#div2-1 ), the top of the div still gets covered by the header. By extending the height of the div by 60px with an invisible `:before`, I'm trying to counter that. – southrop Oct 20 '14 at 04:34
  • Also, here are some screenshots that show my problem exactly: 1. [Regular unstyled `div` has a calculated height that goes above it's regular height as expected](http://puu.sh/cj1Vu.png) 2. [However, styled `.panel` div doesn't](http://puu.sh/cj1WF.png) 3. [For some reason, removing the border makes it work](http://puu.sh/cj1Xs.png). I would've added this to my main post but I can't put more than two links. – southrop Oct 20 '14 at 05:13
  • Can you check out my answer and tell, if this is working for you? – Frederik Witte Oct 20 '14 at 05:20

2 Answers2

0

You don't really need the :before tag for this.

jsfiddle.net/rszqtw80/8/

For your explaining: The > selector selects all direct children of your element.

.first-element > .all-direct-children

<a class="first-element">
    <div class="all-direct-children">
        <div id="notthisone" class="all-direct-children">
        </div>
    </div>
</a>

The element #notthisone won't be affected from your changes. With nth-child, you can select whatever child you want. In your case, I used this to give the first anchor after Div 1, Div 2, etc. A margin-top of 0, So that it's not seperated from your heading(Div 1, Div 2), etc.

Frederik Witte
  • 1,167
  • 2
  • 11
  • 35
  • Unfortunately, this doesn't achieve what I want. It adds 60px above the div, but it changes how the page looks. I don't want an additional 60px of gap in between my panels, unfortunately. – southrop Oct 20 '14 at 05:23
0

After consulting with multiple people, I simply gave up and nested my divs in another div like this.

<div class="container">
    ...

    <div id="div2" class="anchor">
        <div>
            Div 2
        </div>
        <div id="div2-1" class="anchor" >
            <div class="panel panel-default">
                <div class="panel-heading">
                    Div 2-1
                </div>
                <div class="panel-body panel-collapse collapse in">
                    ...
                </div>
                <div class="panel-footer">
                    ...
                </div>
            </div>
            ...
        </div>
    </div>

    ...
</div>

I was hoping to avoid adding yet another layer into my DOM but it seems there's no helping it.

southrop
  • 819
  • 10
  • 19