Search code examples
cssrounded-corners

How to make round corners to both inside of a box and its border?


I guess the title is kind of hard to understand, so I'll explain. I am trying to achieve this effect:

a box which has rounded corners and its border, which also has rounded borders

I've managed to do this, by using the background-clip property:

rounded corners for border but not for inner box

How can I achieve rounded corners for the inner box?

The code I am using:

.radius-all {
  border-radius: 10px;
  -moz-border-radius: 10px;
  -webkit-border-radius: 10px;
}

.template-bg {
  background: #FFF;
  -moz-background-clip: padding;
  -webkit-background-clip: padding;
  background-clip: padding-box;
}

.template-border {
  border: 5px solid rgba(255, 255, 255, 0.2);
}
<header class="body template-bg template-border radius-all">
    <nav>
        <ul>
            <li><a href="#">Link 1</a></li>
            <li><a href="#">Link 2</a></li>
            <li><a href="#">Link 3</a></li>
            <li><a href="#">Link 4</a></li>
        </ul>
    </nav>
</header>


Solution

  • Inner border calculations

    First, you'll need to remove -vendor-background-clip: padding-box or set them to border-box the default in order to achieve the inner border radius.

    The inner border radius is calculated as the difference of the outer border radius (border-radius) and the border width (border-width) such that

    inner border radius = outer border radius - border width

    Whenever the border-width is greater than the border-radius, the inner border radius is negative and you get some awkward inverted corners. Currently, I don't believe there is a property for adjusting the inner-border-radius, so you'll need to calculate it manually.

    In your case:

    inner border radius = 6px - 5px = 1px

    Your new CSS should be:

    .radius-all { border-radius: 6px; -moz-border-radius: 6px; -webkit-border-radius: 6px; }
    .template-bg { background: #FFF; }
    .template-border { border: 5px solid rgba(255, 255, 255, 0.2); }
    

    Simply subtract the border-radius (6px) values from the border-width value (5px) in order to achieve your desired inner-border-radius:


    Code that works for me

    Tested on Firefox 3.x, Google Chrome, and Safari 5.0

     .radius-all { border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; }
    .template-bg { background: #FFF; }
    .template-border { border: 5px solid rgba(0, 0, 0, 0.2); } /* Note that white on white does not distinguish a border */
    

    Adding color overlays in JavaScript

    <script type="text/javascript">
        var bodyBgColor = document.getElementsByTagName('body')[0].style.backgroundColor;;
    
        // insert opacity decreasing code here for hexadecimal
    
        var header = document.getElementsByTagName('header')[0];
        header.style.backgroundColor = bodyBgColor;
    </script>
    

    I'm not entirely sure how to do hexadecimal arithmetic in JavaScript but I'm sure you can find an algorithm in Google.


    Applying General Borders

    Are you using a separate box <div> for your border through its background property? If so, you'll need to apply border-radius and its vendor specific properties on both the border box and the inner box:

    <div id="border-box" style="border-radius: 5px;">
        <div id="inner-box" style="border-radius: 5px;">
        </div>
    </div>
    

    A much more efficient way would simply have the inner-box manage its own border:

    <div id="inner-box" style="border: 4px solid blue; border-radius: 5px">
        <!-- Content -->
    </div>
    

    CSS-wise, you could just declare a .rounded-border class and apply it to every box that will have rounded borders:

    .rounded-borders {
        border-radius: 5px;
        -moz-border-radius: 5px;
        -webkit-border-radius: 5px;
        -khtml-border-radius: 5px;
    }
    

    And apply the class to any boxes that will have rounded borders:

    <div id="border-box" class="rounded-borders">
        <div id="inner-box" class="rounded-borders">
        </div>
    </div>
    

    For a single box element, you'll still be required to declare the border size in order to be shown:

    <style type="text/css">
        #inner-box { border: 4px solid blue; }
    </style>
    
    <div id="inner-box" class="rounded-borders">
    </div>