15

I have a bootstrap column containing a header div which is another bootstrap row, inside a React web app.

The container has the css:

height: calc(100vh - 14em);
overflow-y: hidden;
padding-left: 0;
padding-right: 0;
display: table;
border-left: thin solid #e6e6e6;

And the header row has the css:

border: thin solid #e6e6e6;
border-left: 2px solid #e0e0e0;
height: 6em;
margin-left: 0;
margin-right: 0;
display: table-caption;

This works perfectly in every browser except Safari 10.1, where it disappears when the other elements in the container column are shifted around (via React state). It was working in Safari 9, it only stopped working when I updated.

I've tried removing css properties one at a time, and adding "position: relative" as well as every overflow option, and nothing works. I also tried looking up similar issues (elements disappearing only in Safari), and none of those have worked so far either.

But what's weird is if I change ANY css property in the browser, like if I remove "height: 6em" and then put it back, the div shows. If I start adding another css property, the element shows, before I even finish typing.

I'm pretty sure this is a bug in Safari, since it wasn't a problem in 9 or in any other browser... how can I get it to force an update, or better yet not need one?

Andrew Torr
  • 1,057
  • 3
  • 13
  • 26
  • 2
    Please update your question with a **runnable** [mcve] using Stack Snippets (the `[<>]` toolbar button) demonstrating the behavior, so people can see it happen for themselves, and play around with ways to solve the problem for you. – T.J. Crowder Apr 28 '17 at 15:58
  • A technique often used to force a repaint is to get the `offsetHeight` of the element, as suggested in [this answer](http://stackoverflow.com/a/3485654/1009922) (not sure that changing the display CSS attribute is necessary). – ConnorsFan May 01 '17 at 16:41
  • I have an ugly hack for now that toggles "position: relative" on and off because that doesn't change anything but it forces a redraw. The problem is that different computers calculate things at different speeds, so I have to turn it on and off several times to be sure. I'm working on creating a minimal example, but that's difficult because it's using React... – Andrew Torr May 01 '17 at 17:32
  • 1
    @samottenhoff It would be best if you created an [mcve] of your problem. The current question doesn't provide one and unless you provide means to reproduce the bug, all the answers will be guesses. Post the link to your fiddle in a comment here. At first glance I'd say it would have been better for your own interest to just post a new, proper question, one that would feature some code, rather than offer a bounty on a question that doesn't. – tao May 02 '17 at 20:47
  • Can you add some HTML code too? – TheCrazyProfessor May 03 '17 at 09:25
  • Not really, it's React – Andrew Torr May 03 '17 at 21:43
  • You may want to specify the `box-sizing` style attribute, just to be sure (like `box-sizing: border-box;` or `box-sizing: content-box;`). I read in one blog (dating from 2012) that browsers did not all use the same box model by default for `display: table`. – ConnorsFan May 07 '17 at 01:42

3 Answers3

8

You can try setting -webkit-transform: translate3d(0,0,0); on the element to force GPU processing. That worked for me on a similar issue.

Bogdan
  • 116
  • 7
  • Well, changing the css via state to include this does force a redraw, but the same problem exists - I have to toggle it repeatedly because different computers move at different speeds – Andrew Torr May 02 '17 at 15:15
  • I think if you set it on the element once, it will always be computed by the GPU and you won't need to add it again. – Bogdan May 02 '17 at 17:13
7

Here's the technique I use when I encounter this nasty bug in Safari.

I basically force a redrawing of the element with a css animation loop:

@keyframes forceRedraw {
    from { box-shadow: inset rgba(0,0,0,0) 0 0 0; }
    to { box-shadow: inset rgba(0,0,0,0.0000001) 0 0 0 10px; }
}

.container{
    width: 100px;
    height: 100px;
    background-color: red;
    animation-name: forceRedraw;
    animation-duration: 4s;
    animation-iteration-count:infinite;
}

Hope this helps!

Etienne Martin
  • 10,018
  • 3
  • 35
  • 47
0

I managed to move the offending element into the component below it, since that component was being redrawn each time its state changed. I didn't think I could move it at first but I figured out a way. I guess there's still a bug in Safari, but anyway I found a way around it.

And anyway, if it were necessary toggling a style change several times in a row (loop w/ a timeout) is ugly and horrible but it keeps the element visible, and at least you can limit it to Safari 10:

if (navigator.userAgent.indexOf("Mac OS X 10") > -1
  && navigator.vendor.indexOf("Apple") > -1) {
Andrew Torr
  • 1,057
  • 3
  • 13
  • 26