10

I have a few simple CSS classes for a panel with a header. It works great when the background is a fixed color because I have to use that color to hide the border behind the header text. However, I now want to have a background image instead of a solid color.

Is there a way to have the header element cover up the parent element's border AND allow the background image to show through? I can easily set the color to transparent, but nothing I've found will cover the border other than a solid color or image.

I have a hunch it could be done with JS and reusing the image as the background of the header and setting some offsets based on the position on the page, but that seems overly complicated, and won't work for me since I'd like to account for several layered background images forming a pattern, or fixed attachment which would constantly have to be recalculated.

Is there a way to do this?

Good and Bad Examples

.panel {
    border: 2px solid #000000;
    padding: 1em;
    margin: 1em;
    display: block;
}

.panel-header {
    position: relative;
    top: -1.5em;
    background-color: #ffffff;
    padding-left: 0.4em;
    padding-right: 0.4em;
    font-size: 1.2rem;
    font-weight: bold;
}

.panel-content {
    margin-top: -0.5em; 
}
<div class="panel">
  <span class="panel-header">
    Title Goes Here
    </span>
  <p class="panel-content">Glorious baklava ex librus hup hey ad infinitum. Non sequitur condominium facile et geranium incognito.</p>
  </div>

<hr/>

<div style="background-image: url(http://placekitten.com/510/200); padding: 2em;">
  <div class="panel">
    <span class="panel-header">
      Title Goes Here
      </span>
    <p class="panel-content">Glorious baklava ex librus hup hey ad infinitum. Non sequitur condominium facile et geranium incognito.</p>
    </div>
</div>
Nathan Rabe
  • 665
  • 1
  • 6
  • 10
  • Not sure if I understand what you want. Something like this http://jsfiddle.net/ht27wg5b/? – j08691 Jan 29 '15 at 17:50
  • I've created you a re-usable version that would be really simple to implement across any image. – Aaron Jan 29 '15 at 18:03

3 Answers3

14

I think this is a more useable version, that only requires one extra div and will be transferable to almost any image. Plus and this is a big plus, no extra image section would be required. It's reusable!

.panel-wrapper {
    overflow: hidden;
}

.panel {
    border: 2px solid #000000;
    border-top: 0;
    padding: 1em;
    margin: 1em 0 0;
}

.panel-header {
    position: relative;
    top: -1.5em;
    padding-left: 0.4em;
    padding-right: 0.4em;
    font-size: 1.2rem;
    font-weight: bold;
}
.panel-header:before,
.panel-header:after {
    content: "";
    position: absolute;
    height: 2px;
    background: #000;
    top: 50%;
}
.panel-header:before {
    width: 100px;
    left: -100px;
}
.panel-header:after {
    width: 1000px;
    right: -1000px;
}
.panel-content {
    margin-top: -0.5em; 
}
<div>
    <div class="panel-wrapper">
  <div class="panel">
    <span class="panel-header">
      Title Goes Here
      </span>
    <p class="panel-content">Glorious baklava ex librus hup hey ad infinitum. Non sequitur condominium facile et geranium incognito.</p>
    </div>
    </div>
</div>

<div style="background-image: url(http://placekitten.com/510/200); padding: 2em;">
    <div class="panel-wrapper">
  <div class="panel">
    <span class="panel-header">
      Title Goes Here
      </span>
    <p class="panel-content">Glorious baklava ex librus hup hey ad infinitum. Non sequitur condominium facile et geranium incognito.</p>
    </div>
    </div>
</div>
Aaron
  • 10,187
  • 3
  • 23
  • 39
  • I like the idea of skipping the top border and faking it with :before and :after, and I might use this method on a different project. On this project though, I sometimes have rounded corners to deal with, so I had to go with the accepted answer. – Nathan Rabe Jan 29 '15 at 20:18
7

First of all you need a container div with a background (I've grabbed a random one from the internet).

After that you can use the <fieldset> and <legend> HTML tags to achieve the desired effect.

div {
  padding: 30px;
  background: url(https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcSkAuRoZnkLBZlEYtgL5GJ5w_2Tufpxh5PqkOf-Negy7eL-JGC5Mk-DW-I) no-repeat center center;
  background-size: cover;
}

fieldset {
  border: 2px solid black;
  padding: 10px;
}
<div>
  <fieldset>
    <legend>Personalia:</legend>
    <p>some text here</p>
  </fieldset>
</div>

Here you can see the Fiddle

InSync
  • 4,851
  • 4
  • 8
  • 30
3

This is a common problem.

My solution is:

  1. Set the background of .panel-header as the same of the background image.
  2. Set z-index: 0 to make it to the top layer.
  3. Adjust the background-position property.

When you adjust the background-position, you can also use jQuery to calculate the offset to make it accurate.

Hope it helps, see the snippet.


The effective code is just to add:

.panel-header {
    z-index: 0;
    background-image: url(http://placekitten.com/510/200);
    background-position: -66px -38px;
}

The snnipet:

.panel {
    border: 2px solid #000000;
    padding: 1em;
    margin: 1em;
    display: block;
}

.panel-header {
    position: relative;
    top: -1.5em;
    // here!
    z-index: 0;
    background-image: url(http://placekitten.com/510/200);
    background-position: -66px -38px;
    padding-left: 0.4em;
    padding-right: 0.4em;
    font-size: 1.2rem;
    font-weight: bold;
}

.panel-content {
    margin-top: -0.5em; 
}
<div class="panel">
  <span class="panel-header">
    Title Goes Here
    </span>
  <p class="panel-content">Glorious baklava ex librus hup hey ad infinitum. Non sequitur condominium facile et geranium incognito.</p>
  </div>

<hr/>

<div style="background-image: url(http://placekitten.com/510/200); padding: 2em;">
  <div class="panel">
    <span class="panel-header">
      Title Goes Here
      </span>
    <p class="panel-content">Glorious baklava ex librus hup hey ad infinitum. Non sequitur condominium facile et geranium incognito.</p>
    </div>
</div>
Alfred Huang
  • 17,654
  • 32
  • 118
  • 189
  • 1
    You would have to create these little images and add them in exactly the right place. I think using psuedo elements would work in a better way – Aaron Jan 29 '15 at 17:59
  • @Aaron Yes, good advise in fact, but the essential point is the same. – Alfred Huang Jan 29 '15 at 18:01
  • I know it is possible this way, but these panels can be dynamically generated and placed, and the backgrounds may use background-attachment: fixed; which means updating the position every scroll event, which is not worth the effort for my needs. – Nathan Rabe Jan 29 '15 at 18:04
  • @NathanRabe So you can control the `background-position` with javascript. This answer just shows a solution, a thought, maybe not the best, but a neat one. – Alfred Huang Jan 29 '15 at 18:07