locked
How can I make this CSS3 Transition work in my Metro style app?

    Question

  • I'm creating an App with HTML5/JS. The app structure is similar to the Grid Application template. In my itemDetailPage, main content is an image with some description beneath it.

    Image is initially styled to fit in the page, so the IMG node has the following CSS classes: 

    .itemdetailpage section[role=main] article .item-image {
    	-ms-grid-row: 1;
    	margin-top: 0px;
    	margin-left: 0px;
    	/* Show image at original size */
    	max-width: auto;
    	max-height: auto;
    }
    



    .itemdetailpage section[role=main] article .item-image.fit {
    
    	/* Fit image to page size */
    	max-width: 100%; 
    	max-height: 100%;
    	-ms-transition: all 1s linear;  /* Transition does not seem to work, even if moved from here to other class */
    }

    At some point the app can switch to show the image at its original (natural) size, and can switch back and forth between these two modes (fit Vs original). So in JavaScript I toggle the "fit" class on the IMG node.

    I would expect that toggling between these to CSS classes would cause the transition to kick in, so to see the image growing or shrinking, but instead it's not working.

    What am I doing wrong?

    I know I can change size in JS, but that is causing other problems, and I'd like to represent the two "states" by means of CSS classes. Thanks.

    Wednesday, May 30, 2012 8:22 AM

Answers

  • Hello. Thanks for your explanation. I was not so convinced about it, as I had seen many examples where there's no JS to change single properties, it's all done by CSS.

    Thus I did some more research, and here's what I've found:

    * it's not a problem of Metro as you said. It really depends on how CSS3 transitions works

    * 99% of examples work in CSS-only and the transition happens between some Xxxx class and Xxxx:focus or Xxxx:active. I.e. they use pseudo selectors to change class "automatically" (See nettuts+ as an example)

    * the only way to change CSS class by JS code and still obtain a transition is not to toggle the class (at least not with Win Utils hasClass), but to actually assign it via className property (See SO as an example)

    * even changing className in that way, there's a problem with max-width/-height properties. They are supported in CSS3 transition (as per W3C), but apparently they do not work in my case. At least, I tried with the same code to change opacity (ok), top (ok), width (no), max-width (no). I think it's because they are supposed to work when expressed as lenght or percentage, but I'm toggling between percentage and "auto". 

    Edit: I tried afterwards, avoiding "auto" on max-width/-height and toggling between only numerical values: transition actually works in that way.



    • Edited by GiUmaTo Wednesday, May 30, 2012 10:35 PM
    • Marked as answer by GiUmaTo Thursday, May 31, 2012 8:12 AM
    Wednesday, May 30, 2012 10:29 PM

All replies

  • After you set the style in code, inspect the HTML with the DOM explorer and look at the styles there.  Verify that the class is getting set where you think it is and has the correct value.

    Jeff Sanders (MSFT)

    Wednesday, May 30, 2012 2:43 PM
    Moderator
  • I double checked that the IMG node receives the expected classes. As a matter of fact it toggles between (just) ".item-image" and ".item-image.fit". This is also confirmed from the size of the image, actually switching between fit-page and natural size.

    Also, I can see in the style traces that it has the -ms-transition-xxx properties as in CSS class.

    I also tried to move the -ms-transition property from one class to the other, with no luck. The HTML is coded so that the node starts with both classes "item-image" and "fit" set.

    Wednesday, May 30, 2012 2:49 PM
  • I did some digging and this is not really a Metro issue but a question of how to apply css styles.  Here is what I found.

    Transition applies to the class you define and add to your element.  When you assigned a new class you simply changed the entire class and did not transition.

    Transitions apply to the properties of the element which are set for the class.  So in your case, you want to change the size of the element and not the class associated with the element.

    Here is a simple example you can build on from a blank project:

    HTML:
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>FitImageClassTest</title>
        <!-- WinJS references -->
        <link href="//Microsoft.WinJS.0.6/css/ui-dark.css" rel="stylesheet">
        <script src="//Microsoft.WinJS.0.6/js/base.js"></script>
        <script src="//Microsoft.WinJS.0.6/js/ui.js"></script>
        <!-- FitImageClassTest references -->
        <link href="/css/default.css" rel="stylesheet">
        <script src="/js/default.js"></script>
    </head>
    <body>
    	<p id="title">Click anywhere!</p>
        <img id="foo" src="images/logo.png"  />
    </body>
    </html>
    CSS:
    #title{
        left: 100px;
        top: 100px;
        position:absolute;
        z-index: 2;
    }
    #foo{
    width:50px;
    height:50px;
    position:absolute;
    top:0;
    left:0;
    -ms-transition: all 1s;  
    z-index: 1;
    }
    Javasript:
     WinJS.UI.processAll();
                var f = document.getElementById('foo');
                document.addEventListener('click', function (ev) {
                    if (f.style.width === "100%") {
                        f.style.width = "50px";
                        f.style.height = "50px";
                    }
                    else {
                        f.style.width = "100%";
                        f.style.height = "100%";
                    }
                }, false);
                
    -Jeff

    Jeff Sanders (MSFT)

    Wednesday, May 30, 2012 8:13 PM
    Moderator
  • Hello. Thanks for your explanation. I was not so convinced about it, as I had seen many examples where there's no JS to change single properties, it's all done by CSS.

    Thus I did some more research, and here's what I've found:

    * it's not a problem of Metro as you said. It really depends on how CSS3 transitions works

    * 99% of examples work in CSS-only and the transition happens between some Xxxx class and Xxxx:focus or Xxxx:active. I.e. they use pseudo selectors to change class "automatically" (See nettuts+ as an example)

    * the only way to change CSS class by JS code and still obtain a transition is not to toggle the class (at least not with Win Utils hasClass), but to actually assign it via className property (See SO as an example)

    * even changing className in that way, there's a problem with max-width/-height properties. They are supported in CSS3 transition (as per W3C), but apparently they do not work in my case. At least, I tried with the same code to change opacity (ok), top (ok), width (no), max-width (no). I think it's because they are supposed to work when expressed as lenght or percentage, but I'm toggling between percentage and "auto". 

    Edit: I tried afterwards, avoiding "auto" on max-width/-height and toggling between only numerical values: transition actually works in that way.



    • Edited by GiUmaTo Wednesday, May 30, 2012 10:35 PM
    • Marked as answer by GiUmaTo Thursday, May 31, 2012 8:12 AM
    Wednesday, May 30, 2012 10:29 PM