Centering images that are fading in and out

Twine Version: 2.8.1.0

I am slowly fading one image away and another on top, in the exact same location, and repeating that process for a series of 5 passages. To do this, I have roughly followed HiEv’s Reddit post about cycling images, I’ve just simplified it because I don’t need to cycle back and forth. My stylesheet has the following:

#imgoverlay {
	position: relative;
	width: 80%;
	margin: 0 auto;
	line-height: 0;
}
#backimg {
	position: relative;
	width: 80%;
	max-width: -webkit-max-content;
	max-width: -moz-max-content;
	max-width: max-content;
}
#frontimg {
	display: none;
	position: absolute;
	left: 0;
	width: 80%;
	max-width: -webkit-max-content;
	max-width: -moz-max-content;
	max-width: max-content;
}

#frontimgloop {
	position: absolute;
	left: 0;
	width: 80%;
	max-width: -webkit-max-content;
	max-width: -moz-max-content;
	max-width: max-content;
	-webkit-animation: fade-loop 8s;
}
@-webkit-keyframes fade-loop {
	0% {
		opacity: 0;
	}
	100% {
		opacity: 1;
	}
}

and my passage has the following, which is working as intended:

<div id="imgoverlay">
	<img id="backimg" src="images/SketchBase.png">
	<img id="frontimgloop" @src="'images/' + $toFadeIn + '.png'">
</div>

However, if I try to center the images - and I need them all to be perfectly centered - it breaks. The faded-in image (2) no longer aligns with the faded-out image (1); instead, 2 now has a center point to the left of 1. I tried using the center tags in my passages, like so:

<center><div id="imgoverlay">
	<img id="backimg" src="images/SketchBase.png">
	<img id="frontimgloop" @src="'images/' + $toFadeIn + '.png'">
</div></center>

That didn’t work. Is there something else I should be using?

I’m sure there is an easy css/html answer to this and I am misunderstanding a few things because I didn’t fully get the HiEv script that I was adapting anyway! I’m still learning a lot about images in Twine and I haven’t found an answer that worked elsewhere.

1 Like

The most straightforward way is to change the CSS for #imgoverlay.

First change position: relative; to position: absolute;. Absolute positioning means the div will be aligned based on the page itself instead of relative to the div’s original position.

Next add left: 18%; This means the div is a varying distance from the left side of the page no matter how big the browser window is. You’ll probably need to change 18% to a different amount depending on the size of your images.

We end up with:

#imgoverlay {
	position: absolute;
	left: 18%;
	width: 80%;
	margin: 0 auto;
	line-height: 0;
}

This isn’t truly centered but it’s the most straightforward way of doing it IMO. BTW I tried this in a blank HTML page and not Twine … it’s possible that the Sugarcube layout will mess with it further.

1 Like

This works well enough, thank you! I got it centered - at least, it looks centered, which is good enough for me.

If you don’t mind, could you explain why it’s necessary to figure out what seems to be an arbitrary number for that left property?

1 Like

Sure. Basically you’re telling the browser what percent of the screen the image doesn’t occupy, divided by half.

Math

When I was testing it I had a browser width of 1000px and an image about 650px wide.

That leaves 350px of blank space left over. You divide 350px in half to get ~180px of blank space on the left side.

180px of 1000px is 18%, so I used left: 18% to center it.

In reality I just eyeballed it and kept tweaking, just like you probably did.

One thing to note is the units we used. Sometimes you might need to use left: 180vw instead of left: 180% . Either one works in this example.

This page explains the difference between vw and %. The definitions might not be useful to you on their own but if you tweak the examples under “Try It,” you’ll notice some differences based on whether you apply vw or % to certain things.

1 Like

Thank you for explaining, and for linking to more information! I had no idea that so many units existed and a lot of stuff I’ve seen in the past is retroactively making more sense.

1 Like

Okay, follow-up question. P.B. Parjeter’s response works, BUT I have since realized that I have two complications that remain present. Notably, the following:

  1. If the sidebar is out or in, the image orientation remains the same (because it’s absolute, I assume). How would I get the image to “pop” back and forth between sidebar in/out, keeping it centered no matter what?

  2. If there is any text beneath the image, the image overrides it and is laid on top - again, I assume, because it’s absolute.

Any ideas, kind people?

1 Like

You’re right, using absolute in that way was an oversight on my part.

In fact, the parent element (#imgoverlay) should be relative and the other three should be absolute.

So you end up with this:

#imgoverlay {
	position: relative;
	width: 80%; 
	left: 18%; /* this needs to be adjusted */
}
#backimg {
	position: absolute;
  	top: 0;
	width:  80%;
	max-width: -webkit-max-content;
	max-width: -moz-max-content;
	max-width: max-content;
}
#frontimg {
	display: none;
	position: absolute;
    top: 0;
	width:  80%;
	max-width: -webkit-max-content;
	max-width: -moz-max-content;
	max-width: max-content;
}

#frontimgloop {
	position: absolute;
    top: 0;
	width:  80%;
	max-width: -webkit-max-content;
	max-width: -moz-max-content;
	max-width: max-content;
	-webkit-animation: fade-loop 8s;
}
@-webkit-keyframes fade-loop {
	0% {
		opacity: 0;
	}
	100% {
		opacity: 1;
	}
}
Explanation

Basically, we’ve moved the parent element relative to its original starting position. Its edges now serve as absolute reference starting point for the child elements.

If the child elements were outside of the div, absolute positioning would treat the web page itself as a reference point.



As you noticed, this doesn’t effect the positioning of any text outside of the divs that you made for the image boxes.

By making the #imgoverlay div relative, it’s no longer a static element that goes along with the page flow.

That means we need to tell the browser the height of #imgoverlay with min-height. You’ll need to tweak this number to a bit less than the image ratio in vw units — best to eyeball it but there is a way to calculate.

Finally, because this method is imperfect, we need to add overflow: hidden. This will just crop a bit of the picture off if it extends past the bottom.

We end up with

#imgoverlay {
	position: relative;
	width: 80%; 
	left: 18%; /* this needs to be adjusted */
  	min-height: 53vw; /* this needs to be adjusted */
  	overflow: hidden;
}

Hopefully this works with whatever other CSS changes have been made so far. I worked from a blank Sugarcube game this time around.

1 Like

Thank you for being so thorough! Shifting the absolute/relative properties around like you specified has fixed both the problems :sparkles:

1 Like

Okay, I’m back YET AGAIN with (hopefully) a last question. I’d like to add another image that fades in, and this image is a little bigger. It’s supposed to look like a picture frame that encloses the image being faded in - the art. (The reason why the frame has to be a different image than the art is that the frame appearance will change based on the player’s choices, and I REALLY do not want to create the 100+ image file versions this would necessitate if I combined the art and frame.)

Right now, the way it’s written, the frame image will always overlap the art no matter the frame’s actual width and height. That much makes sense to me. So what do I have to change to make the frame image proportional to, but bigger than, the art image?

I assume I need to create a new element that controls the frame image, and change either the max-width: -webkit-max-content value, the max-width: -moz-max-content value, or the max-width: max-content value. However, changing them each individually has not yielded the results I want.

You can use CSS to assign a border to an element, and that border can be an image (border-image) instead of just lines.

note: The border-image documentation I linked to includes a detailed example explaining how to use different parts of a single image file to represent the individual corners & sides of a image based border.

2 Likes

Thank you! I was familiar with borders, but not with border-images. I’ve tried for a few days to wrap my head around all the elements I would need to nail to make this idea work, so I’m just going to simplify it and not use the border at all. But at least I get it now in theory.

1 Like