QuestionerNo7
QuestionerNo7

Reputation: 620

Display issue with CSS viewport units

I'm working on a child theme of WP's Twentyseventeen, which uses VH in order to adjust certain heights, such as the header portion. In the header all I really want to change is to add a sort of slanted divider to make it more "stylish" but no matter what I do, I'm getting the following issue in certain displays:

Screenshot of issue

As you can see, 1px of the background is showing below the divider. (BTW, this doesn't only happen in mobile displays, and it happens in several browsers.)

Now, here's my code pertaining to this part (as well as 2017's code that I know 2017 has something to do with this section; but I can't be sure the theme doesn't have some code or script somewhere that's affecting this behaviour):

HTML:

<div class="custom-header">

    <div class="custom-header-media">
        <?php the_custom_header_markup(); ?>
    </div>

    <?php get_template_part( 'template-parts/header/site', 'branding' ); ?>

    <div class="custom-header-bottom-divider">
        <svg id="divider-bottom" xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100" viewBox="0 0 100 100" preserveAspectRatio="none"><path d="M0 100 L100 0 L100 100 Z"></path></svg>
    </div>

</div><!-- .custom-header -->

CSS:

.custom-header {
    position: relative;
    overflow: hidden;
}

.has-header-image.twentyseventeen-front-page .custom-header,
.has-header-video.twentyseventeen-front-page .custom-header,
.has-header-image.home.blog .custom-header,
.has-header-video.home.blog .custom-header {
    display: table;
    height: 300px;
    height: 75vh;
    width: 100%;
}

.custom-header-media {
    bottom: 0;
    left: 0;
    overflow: hidden;
    position: absolute;
    right: 0;
    top: 0;
    width: 100%;
}

.custom-header-media:before {
    /* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#000000+0,000000+100&0+0,0.3+75 */
    background: -moz-linear-gradient(to top, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.3) 75%, rgba(0, 0, 0, 0.3) 100%); /* FF3.6-15 */
    background: -webkit-linear-gradient(to top, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.3) 75%, rgba(0, 0, 0, 0.3) 100%); /* Chrome10-25,Safari5.1-6 */
    background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.3) 75%, rgba(0, 0, 0, 0.3) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#00000000", endColorstr="#4d000000", GradientType=0); /* IE6-9 */
    bottom: 0;
    content: "";
    display: block;
    height: 100%;
    left: 0;
    position: absolute;
    right: 0;
    z-index: 2;
}

.has-header-image .custom-header-media img,
.has-header-video .custom-header-media video,
.has-header-video .custom-header-media iframe {
    position: fixed;
    height: auto;
    left: 50%;
    max-width: 1000%;
    min-height: 100%;
    min-width: 100%;
    min-width: 100vw; /* vw prevents 1px gap on left that 100% has */
    width: auto;
    top: 50%;
    padding-bottom: 1px; /* Prevent header from extending beyond the footer */
    -ms-transform: translateX(-50%) translateY(-50%);
    -moz-transform: translateX(-50%) translateY(-50%);
    -webkit-transform: translateX(-50%) translateY(-50%);
    transform: translateX(-50%) translateY(-50%);
}

.custom-header-bottom-divider {
    position: absolute;
    bottom: 0;
    left: 50%;
    width: 100%;
    min-width: 1000px;
    text-align: center;
    line-height: 1;
    transform: translateX(-50%);
    -webkit-transform: translateX(-50%);
    -moz-transform: translateX(-50%);
    -o-transform: translateX(-50%);
    -ms-transform: translateX(-50%);
    z-index: 2;
}

.custom-header-bottom-divider svg {
    display: block;
    fill: #fff;
}

I'm 99% sure this has to do with the fact that 2017 uses VH to establish the header's height. I.e. this means that often the result in pixels won't be an integer but rather something like 932.45. Now, I'm thinking that in theory the browser can't position an object between two pixels, but if it's rounding up or down, then I'm thinking for some reason there could be a discrepancy between the pixel it takes to be 0 for bottom: 0 and the actual pixel it takes to be the bottom border of the header, thereby positioning the child 1px above the actual bottom.

Temp Solution / Workaround:

So this isn't an actual solution, at least not as far as I'm concerned. It's just a temp fix until I can figure out what's going on and how to really solve it. It should be pretty straightforward: if you set an element's height through CSS respective to the viewport, a child element set to bottom: 0 should actually be placed at the absolute bottom. But it's not happening for some reason. Perhaps it's a known issue with viewport units or perhaps the 2017 theme has some other code os script that's mucking about. At any rate, I'm now using JS to manage the issue:

var headerHeight = $customHeader.innerHeight(); 
$customHeader.animate({height: headerHeight});

I corroborated that innerHeight actually retrieves the height as displayed, i.e. in full pixels—integer values—, as a pose to the precise height that is given through vh, which tends to have decimals.

So I'm dynamically resetting the height to that integer value, thereby avoiding the need for the browser to round up or down when displaying.

I believe the issue is that, for some reason, the parent's height and the child's position are being drawn apart when rounding; or the child's position is being set before the parent's height is rounded. At any rate, I'm pretty sure that that 1px gap has to do with the fact that non-integer values are involved in the CSS.

Upvotes: 0

Views: 177

Answers (1)

Levi
Levi

Reputation: 46

You could try modifying the bottom attribute for the divider, changing it to -1px

.custom-header-bottom-divider {
    position: absolute;
    bottom: -1px;
    left: 50%;
    width: 100%;
    min-width: 1000px;
    text-align: center;
    line-height: 1;
    transform: translateX(-50%);
    -webkit-transform: translateX(-50%);
    -moz-transform: translateX(-50%);
    -o-transform: translateX(-50%);
    -ms-transform: translateX(-50%);
    z-index: 2;
}

Upvotes: 2

Related Questions