I've modified my previous Sugarcane passage transition code to allow you to define your own transitions with CSS.
The code
First, include this code in a script passage:
History.prototype.display=function(d,b,a){var c=tale.get(d);this.history.unshift({passage:c,variables:clone(this.history[0].variables)}); this.history[0].hash=this.save();var e=c.render();e.style.visibility="visible";if(a!="offscreen"){var p=$("passages"); for(var i=0;i<p.childNodes.length;i+=1){var q=p.childNodes[i];q.classList.add("transition-out"); setTimeout(function(){p.removeChild(q);},1000);}e.classList.add("transition-in"); setTimeout(function(){e.classList.remove("transition-in");},1);p.appendChild(e);}if((a=="quietly")||(a=="offscreen")){e.style.visibility="visible"; }if(a!="offscreen"){document.title=tale.title;this.hash=this.save();document.title+=": "+c.title; window.location.hash=this.hash;window.scroll(0,0);}return e;};
What this does is remove the default JavaScript transition from Sugarcane, and cause the outgoing passage to gain a "transition-out" class, and the incoming passage to instantly gain and lose a "transition-in" class. This enables you to define new passage transitions by styling these 3 classes using CSS.
CSS Examples
In order for there to be a transition, you must specify the transition
property for your passage elements. A very basic example is as follows:
.passage { transition: 0.25s linear; -webkit-transition: 0.25s linear; }The
transition
property causes elements to transition between styles when they gain and lose them, in a specific way. In this case, it's a quarter-second, purely linear transition. (Other options than "linear" are listed here.) The maximum duration time before the departing passage is removed is 1 second.
The current versions of Opera, Firefox and IE support the plain transition property, but you need to also include the -webkit variant in order to work in Chrome and Safari (you can also include -khtml-transition
for Konqueror users, few though they may be).
Now that you've defined the transition itself, you can define the styles that the passages can transition from and to.
A very basic example:
.transition-in { position:absolute; opacity:0; }When a new passage arrives, its style will transition from the "transition-in" style to the normal passage style. In this case, it starts invisible ("opacity:0") and fades in to visibility. Note the "position:absolute" - both "transition-in" and "transition-out" should have either position:absolute or position:fixed if you want them to neatly appear above or below each other.
.transition-out { position:absolute; opacity:0; }
A broad number of CSS attributes can be used with this technique. Experiment!
Combining with tag-based CSS
If you use my tag-based passage CSS code, you can tie transitions to passages tagged with a particular tag. For instance, to bind the "dissolve" transition to passages tagged with "t8n-dissolve":
body[data-tags~=t8n-dissolve] .transition-in { position:absolute; opacity:0; } body[data-tags~=t8n-dissolve] .passage { transition:1s; -webkit-transition: 1s; } body[data-tags~=t8n-dissolve] .transition-out { position:absolute; opacity:0; }I recommend prefixing all transition-based tags with something identical, like "t8n" (a numeronym of "transition"). This way, you can then define a default transition to be used only when no "t8n" tags are present:
body:not([data-tags*=t8n]) .transition-in { opacity:0; transform: translate(0,3rem); -webkit-transform: translate(0,3rem); position:absolute; } body:not([data-tags*=t8n]) .passage { transition: 2s; -webkit-transition: 2s; } body:not([data-tags*=t8n]) .transition-out { opacity:0; transform: translate(0,-3rem); -webkit-transform: translate(0,-3rem); position:absolute; }
[data-tags*=t8n]
selects elements whose tags contain "t8n", and :not()
selects elements that do not fulfill the requirement in the brackets.)
It's important that if you use multiple transitions, the default transition should be guarded using body:not([data-tags*=t8n])
, so that its code doesn't interfere with the other transitions' code.
To see an example where the first four passages are tagged "t8n-dissolve" and the rest are not, see here.
Live examples
All examples are "The Sky in the Room" by Porpentine.
Fade in (the default transition)
.transition-in { opacity:0; position:absolute; } .passage:not(.transition-out) { transition: 1s; -webkit-transition: 1s; } .transition-out { opacity:0; position:absolute; }
:not(.transition-out)
means that the transition is applied only for the incoming passage - the departing one instantly gets opacity:0. Note that specifying passage.transition-in
would not do anything, since it is by removing the transition-in class that the transition is initiated.
.transition-in { opacity:0; position:absolute; } .passage:not(.transition-out) { transition: 0.8s steps(3); -webkit-transition: 0.8s steps(3); } .transition-out { opacity:0; position:absolute; }
.transition-in { opacity:0; position:absolute; } .passage { transition: 0s 1s; -webkit-transition: 0s 1s; } .passage.transition-out { transition: 1s; -webkit-transition: 1s; } .transition-out { opacity:0; position:absolute; }
Vertical wipe
Sadly, this currently only works if you give the passage div a fixed width and height.
If you use this, replace all instances of "1200px" and "800px" with dimensions appropriate for your story.
.transition-in { clip: rect(0px, 1200px, 0px, 0px) !important; } .passage { clip: rect(0px, 1200px, 800px, 0px); width: 1200px; height: 800px; position: absolute; transition: 1s linear; -webkit-transition: 1s linear; } .transition-out { clip: rect(800px, 1200px, 800px, 0px); }
.transition-in { opacity:0; transform: scale(0.8,0.8); -webkit-transform: scale(0.8,0.8); position:absolute; } .passage { width: calc(100% - 12em); // Necessary to keep the zoom origin point consistent. width: -webkit-calc(100% - 12em); transition: 0.5s ease-out; -webkit-transition: 0.5s ease-out; } .transition-out { opacity:0; transform: scale(2,2); -webkit-transform: scale(2,2); position:absolute; }
Fast scroll up
Ideally you would use "vh" (viewport height) units instead of "rem" (root em) units, but not enough browsers support it yet. ;_;
You can also make it a slow fading scroll if you change the lengths to something short (like 3rem).
.transition-in { opacity:0; transform: translate(0,-100rem); -webkit-transform: translate(0,-100rem); position:absolute; } .passage { transition: 1s; -webkit-transition: 1s; } .transition-out { opacity:0; transform: translate(0,100rem); -webkit-transform: translate(0,100rem); position:absolute; }
Garage door
This would work well with a story whose passage divs have a fixed width and height, but unlike the vertical wipe it isn't strictly necessary.
.transition-in { opacity:0; position:absolute; } .passage { background-color: #000; transition: 1s ease-in; -webkit-transition: 1s ease-in; } .transition-out { position:absolute; z-index:3; transform: translate(0,-200%); -webkit-transform: translate(0,-200%); }
.transition-in { color:transparent; text-shadow: #fff 0 0 1em; position:absolute; } .passage:not(.transition-out) { transition: 1s; -webkit-transition: 1s; } .transition-out { opacity:0; position:absolute; }
.transition-in { color:transparent; text-shadow: #fff -4em 0 1em, #fff 4em 0 1em; position:absolute; } .passage:not(.transition-out) { transition: 1s; -webkit-transition: 1s; } .transition-out { opacity:0; position:absolute; }
Attachment | Size |
---|---|
tsitr_fadein.html | 92.69 KB |
tsitr_fadeout.html | 92.74 KB |
tsitr_scrollup.html | 92.82 KB |
tsitr_focus.html | 92.76 KB |
tsitr_sillyrotate.html | 92.92 KB |
tsitr_retrofadein.html | 92.71 KB |
tsitr_spin5seconds.html | 92.98 KB |
tsitr_blur_merge.html | 92.74 KB |
tsitr_garagedoor.html | 92.78 KB |
tsitr_zoomin2.html | 92.92 KB |
tsitr_verticalwipe.html | 92.87 KB |
tsitr_t8ntest.html | 93.84 KB |