-1

tl;dr: As stated in my title: CSS transform rotate not rendering on Webkit / iPhone (but works in Chrome Devtools device toolbar).

Update: I've also created a separate GitHub issue for this which is more concise (arguably easier to read) and without code excerpts in it, here.


Just for some context (in case it matters): I'm calling my Express API from React, getting images and their associated orientations which I mapped to values 0, 180, and 270 degrees clockwise from the vertical (from the EXIF data), then using CSS to rotate them once I already do an initial render. I'm also lazy-loading images as I scroll down the page, so am using the new IntersectionObserver API which requires the polyfill for WebKit / Safari (so I've included that polyfill in a script tag of the root index.html in my public directory). This all works fine from Google Chrome without the polyfill, and from Safari with the polyfill, but from Chrome / Safari on the iPhone, it doesn't rotate the images.

Here's some relevant code:

// LazyImage.js
render() {
    const { className } = this.props;
    const transformRotationValue = `rotate(${360 - this.state.orientation}deg)`;
    const styles = {
      '-webkit-transform':  transformRotationValue,
      '-moz-transform':     transformRotationValue,
      '-ms-transform':      transformRotationValue,
      '-o-transform':       transformRotationValue,
      transform:            transformRotationValue,
      height:               '500px',
    }
    return (
      <Fragment>
        <p>
          Date: {this.state.date}
        </p>
        <img alt={this.state.date} className={className} style={styles} ref={el => this.element = el} />
      </Fragment>
    );
  }

Also, I'm not very good with CSS, but here's my CSS code:

/* PhotoFeed.css */
/* https://stackoverflow.com/questions/14142378/how-can-i-fill-a-div-with-an-image-while-keeping-it-proportional#answer-20341542 */
:local(.photos) {
  width: inherit;
  flex-shrink: 0;
  min-height: 100%
}
:local(.photoContainer) {
  height: 500px;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  margin-top: 2px;
}

which corresponds to this code in the React Component:

// PhotoFeed.js
return (
              <div className={styles.photoContainer} key={idx}>
                <LazyImage className={styles.photos} src={`${apiRootURL}/photos/demo/${fileName}?token=${Authentication.getToken()}`}/>
              </div>
            );

The full code is also available for both the server-side and the client-side code (in case anybody wants to actually run the entire program, though the client code is the main code in question here). The demo code is also live at this website and can be accessed like so, in case anybody wants to test the front-end of the website from some kind of browser tool.

I also looked into some of the advice here, but I just don't understand why the CSS isn't working on the iPhone, but it is working on both Chrome and Safari on my macOS.


Some Updates

UPDATE 1:

I tried this, as @MohammadRF suggested in the comment, but it still doesn't work. In more detail, I added those same classes to my CSS, and update my react code as follows:

const styles = {
      // '-webkit-transform':  transformRotationValue,
      // '-moz-transform':     transformRotationValue,
      // '-ms-transform':      transformRotationValue,
      // '-o-transform':       transformRotationValue,
      // transform:            transformRotationValue,
      height:               '500px',
    }
    return (
      <Fragment>
        <p>
          Date: {this.state.date}
        </p>
        <img alt={this.state.date} className={className + ` rotate${360 - this.state.orientation}`} style={styles} ref={el => this.element = el} />
      </Fragment>
    );

That doesn't work because the CSS just doesn't even get applied from the className, even on the browser without webkit (although the class list does get updated in the rendered HTML code). So my original (and current) solution works a bit better so far.


Update 2:

I just realized my Chrome DevTools were giving me the following warnings {face-palm}:

index.js:1446 Warning: Unsupported style property -webkit-transform. Did you mean WebkitTransform?

index.js:1446 Warning: Unsupported style property -moz-transform. Did you mean MozTransform?

index.js:1446 Warning: Unsupported style property -ms-transform. Did you mean msTransform?

index.js:1446 Warning: Unsupported style property -o-transform. Did you mean OTransform?

So now I've fixed it so that the warnings don't show up:

    const rotationValue = 360 - this.state.orientation;
    const transformRotationValue = `rotate(${rotationValue}deg)`;
    const styles = {
      WebkitTransform:  transformRotationValue,
      MozTransform:     transformRotationValue,
      msTransform:      transformRotationValue,
      OTransform:       transformRotationValue,
      transform:        transformRotationValue,
      height:           '500px',
    }

...but it's still properly rotating on my macOS Chrome/Safari but still not rotating on the iPhone browsers.

user3773048
  • 5,839
  • 4
  • 18
  • 22
  • Check this stackoverflow issue as it might be related to yours: https://stackoverflow.com/questions/24658365/img-tag-displays-wrong-orientation – M Reza Jan 18 '19 at 06:15
  • Thanks, but that isn't working. I'm also using the npm exif package, but when I update the className like they did it there, it doesn't take effect / render in the UI. I modified my code accordingly as suggested there (https://stackoverflow.com/questions/24658365/img-tag-displays-wrong-orientation#answer-50591539) but no good. – user3773048 Jan 18 '19 at 06:40
  • Why'd I get a downvote? Should I revise my question to make it shorter and maybe trim out the updates? I honestly think all the text and updates might help somebody else who is later Google-searching for this when/if they're stuck on this weird issue. If I find out the solution to this I'll make sure there's an answer updated on this page. – user3773048 Jan 18 '19 at 09:00

2 Answers2

0

The main issue was identifying the problem. Here's the face-palm moment: It turns out the the browsers (Chrome and Safari) on the iPhone automatically orient the jpeg images to the desired orientation, but Desktop browsers don't do that. Once I realized this, it was a 5-minute fix. I looked through this MDN page and this tutorial to check the user agent string on the iPhone from Safari dev tools, then came up with this simple solution for my render method:

render() {
    let { className } = this.props;
    const styles = {
      transform:  'rotate(0deg)',
      height:     '500px',
    }
    if (navigator.userAgent.indexOf('iPhone') === -1) {
      styles.transform = `rotate(${360 - this.state.orientation}deg)`;
    }
    return (
      <Fragment>
        <p>
          Date: {this.state.date}
        </p>
        <img alt={this.state.date} className={className} style={styles} ref={el => this.element = el} />
      </Fragment>
    );
  }
user3773048
  • 5,839
  • 4
  • 18
  • 22
0

The answer is basically this:

Make sure you also set the default property: rotate(0deg)

Not setting it works on Chrome, but it won't work on iOS and Edge

Stefan S
  • 301
  • 2
  • 3