How can I stop Harlowe injecting inline-styles into "tw-story" when switching passages?

Twine Version: 2.9.2

UPDATE: I’ve added a version without Javascript in my reply below

UPDATE #2: I seem to have identified the culprit, see my next reply

ORIGINAL POST:
I am working on a prototype that renders my story (or rather the main container) in an aspect ratio of 4:3, regardless of screen size. While this functionality is working perfectly, I ran into another problem:

Everytime a new passage is selected, the main container is initially rendered smaller – in 4:3, mind you, but smaller than 100% (upon loading the game, it is rendered correctly).

After a lot of research I think I may know what is happening: This may be due to Harlowe removing the tw-story element when switching passages before rendering the new passage in a new tw-story element, which is then appended to the html, so it’s kind of nested. When inspecting the outer-container div in chrome, I can see Harlowe injects inline styles when moving to a new passage which reduce the size of the outer-container

I added some css for the tw-passage which helped in that the new passage resizes back to 100% BUT with a delay of a second or two (this becomes especially apparent full screen).

Which isn’t nice. I would of course prefer for every passage to be immediately at 100% on load.

I am at my wits end. So my questions ultimately are:

  • Can I solve this somehow without removing the aspect ratio functionality (this is kind of important for my project)?
  • Is there a better way to stop Harlowe from injecting inline styles when moving passages?
  • At the very least: Can I reduce the delay of the resizing?
  • Optionally: If there is a better way to force the aspect ratio (which also solves the other problems, I am very open to it!

Thank you ever so much in advance to anyone who reads this and tries to help!

You can test the behaviour here.

You can view my source code here (github link).

Here is the stylesheet:


 * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html, body {
    height: 100%;
    width: 100%;
    overflow: hidden;
    margin: 0;
    padding: 0;


tw-sidebar {
  display: none;
}

body {
    background: grey;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    overflow: hidden; /* Prevents scrollbars when viewport is smaller than the container */
    font-size: 1.5em;
  font-family: Arial, sans-serif;
    color: white;
  margin: 0;
  padding: 0;
}
  
  tw-story {
     font-size: 1.5em;
  font-family: Arial, sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    overflow: hidden; /* Prevents scrollbars when viewport is smaller than the container */
    color: white;
  margin: 0;
  padding: 0;
}
  
  
  tw-passage {
       height: 100%;
  margin-left: auto;
  margin-right: auto;
}


p {
    font-size: 1em;
  	line-height: 1.45;
}
  
 



.outer-container {
    /* Maintain a 4:3 aspect ratio */
    aspect-ratio: 4 / 3;
    width: 100%;
    height: 100%;
    max-width: calc(100vh * 4 / 3);  /* Constrain based on height */
    max-height: calc(100vw * 3 / 4); /* Constrain based on width */
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: blue;
}





/* Inner container  */
.inner-container {
    aspect-ratio: 4 / 3;
    width: 100%;
    height: 100%;
    max-width: 100%;
    max-height: 100%;
    background-color: transparent;
    display: grid;
    grid-template-columns: 1fr 2fr 1fr;
    grid-template-rows: repeat(6, 1fr);
    gap: 20px;
    padding: 20px;
}


/* Styling the boxes */
.box {
    background-color: none;
    
}

/* Left column */


.middle-box {
    grid-column: 1 / 3;
    grid-row: 2;
    border: 1px solid white;
    padding: 15px;
    background-color: green;
}
  





/* Middle column */
.head {
    grid-column: 1 / span 2;
    grid-row: 1 / 2;
   border: 1px solid white;
    padding: 15px 15px 5px 15px;
    background-color: pink;
}



.lower-box {
    grid-column: 1 / 3;
    grid-row: 2 / 7;
  	background-color: pink;
    border: 1px solid white;
}



/* Right column with equal height boxes */

.side-box-1 {
    grid-column: 3 / 4;
    grid-row: 1 / 2;
    padding: 0;
  	border: 1px solid white;
    background-color: pink;
}


.side-box-2 {
    grid-column: 3 / 4;
    grid-row: 2 / 3;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}

.side-box-3 {
    grid-column: 3 / 4;
    grid-row: 3 / 4;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}

.side-box-4 {
    grid-column: 3 / 4;
    grid-row: 4 / 5;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}

.side-box-5 {
    grid-column: 3 / 4;
    grid-row: 5 / 6;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}

.side-box-6 {
    grid-column: 3 / 4;
    grid-row: 6 / 7;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}




/* Breakpoints for different screen sizes */

/* For large screens (1920px and above) */
@media screen and (min-width: 1920px) {
    tw-story {
        font-size: 2em;
        line-height: 1.45;
    }
}

/* For medium screens (between 1600px and 1920px) */
@media screen and (max-width: 1920px) and (min-width: 1600px) {
    tw-story {
        font-size: 1.5em;
        line-height: 1.45;
    }
}

/* For smaller desktop screens (between 1280px and 1600px) */
@media screen and (max-width: 1600px) {
    tw-story {
        font-size: 1.2em;
        line-height: 1.45;
    }
}

/* For smaller desktop screens (between 1280px and 1600px) */
@media screen and (max-width: 1200px) {
    tw-story {
        font-size: 1em;
        line-height: 1.45;
    }
}

Here is the JavaScript:

// aspect ratio
$(document).ready(function() {
$(window).on('resize passage:start', function () {
    var container = $('.outer-container');
    var aspectRatio = 4 / 3;
    
    var width = container.width();
    var height = container.height();
    var windowAspectRatio = window.innerWidth / window.innerHeight;

    if (windowAspectRatio > aspectRatio) {
        container.height(window.innerHeight);
        container.width(window.innerHeight * aspectRatio);
    } else {
        container.width(window.innerWidth);
        container.height(window.innerWidth / aspectRatio);
    }
}).trigger('resize');
});

Here is the html:

    {
   <div class="outer-container">

    <div class="inner-container">
        
        <div class="box head">
        	Test
        </div>
        
              <div class="box middle-box">
        	middle-box
        </div>
        
        <div class="box lower-box"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
        
        <p>(link: "Link 1")[(go-to: "Test 2")]</p>
        </div>
        
        <div class="box side-box-1">
            side box 1
        </div>
     
        <div class="box side-box-2">
        	side box 2
        </div>
        
        <div class="box side-box-3">
        	side box 3
        </div>
       
       <div class="box side-box-4">
       	    side box 4
       </div>
        
        <div class="box side-box-5">
        	side box 5
        </div>
        
        <div class="box side-box-6">
        	side box 6
        </div>
       
       </div>
      
      </div>}

Thank you!

1 Like

I think the short answer is, Harlowe doesn’t expect you to be using JS, and it doesn’t play nicely with any reformatting not done with it’s own macros.

Harlowe is not designed for extension. Although I’ve not seen this particular issue before, I have seen endless attempts at animations/custom interfaces, hindered by the way Harlowe double-renders everything, and it’s reliance on inline styling and invisible DOM elements.

For a slightly longer answer, I don’t think you can stop the engine injecting styles, but you might be able to override them with !important if you can work out what’s breaking? Alternatively, you might need to inject your own styles at the right moment?

1 Like

Thank you for the reply. What I’ve done in the meantime: Created a version without JavaScript that you can test here.

As you can see on the first couple of passages, I was able to solve the problem – but then in passage 5 and 6 (where I use different layouts) the problem pops up again (even though outer-container and inner-container haven’t changed). Then going back to the first passage it’s ok again. For the life of me I cannot see why this is happening. Any idea?

Here is the stylesheet:


 * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html, body {
	height: 100%;
  	width: 100%;
    overflow: hidden;
    margin: 0;
    padding: 0;


tw-sidebar {
  display: none;
}

body {
    background: grey;
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: hidden; /* Prevents scrollbars when viewport is smaller than the container */
    font-size: 1.5em;
  font-family: Arial, sans-serif;
    color: white;
  margin: 0;
  padding: 0;
}
  
  tw-story {
     font-size: 1.5em;
  font-family: Arial, sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: hidden; /* Prevents scrollbars when viewport is smaller than the container */
    color: white;
  margin: 0;
  padding: 0;
}
  
  
 /* tw-passage {
       height: 100%;
  margin-left: auto;
  margin-right: auto;
}
  */


p {
    font-size: 1em;
  	line-height: 1.45;
}
  
 



.outer-container {
    /* Maintain a 4:3 aspect ratio */
    aspect-ratio: 4 / 3;
    width: 100%;
    height: 100%;
    max-width: calc(100vh * 4 / 3);  /* Constrain based on height */
    max-height: calc(100vw * 3 / 4); /* Constrain based on width */
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: blue;
}





/* Inner container  */
.inner-container {
    aspect-ratio: 4 / 3;
    width: 100%;
    height: 100%;
    max-width: 100%;
    max-height: 100%;
    background-color: transparent;
    display: grid;
    grid-template-columns: 1fr 2fr 1fr;
    grid-template-rows: repeat(6, 1fr);
    gap: 20px;
    padding: 20px;
}
  


/* Styling the boxes */
.box {
    background-color: none;
    
}
  
  .fullbox {
    grid-column: 1 / span 4;
    grid-row: 1 / span 6;
    border: 1px solid white;
    background-color: pink;
    padding: 30px;
}

/* Left column */


.middle-box {
    grid-column: 1 / 3;
    grid-row: 2;
    border: 1px solid white;
    padding: 15px;
    background-color: green;
}
  





/* Middle column */
.head {
    grid-column: 1 / span 2;
    grid-row: 1 / 2;
   border: 1px solid white;
    padding: 15px 15px 5px 15px;
    background-color: pink;
}



.lower-box {
    grid-column: 1 / 3;
    grid-row: 2 / 7;
  	background-color: pink;
    border: 1px solid white;
}



/* Right column with equal height boxes */

.side-box-1 {
    grid-column: 3 / 4;
    grid-row: 1 / 2;
    padding: 0;
  	border: 1px solid white;
    background-color: pink;
}


.side-box-2 {
    grid-column: 3 / 4;
    grid-row: 2 / 3;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}

.side-box-3 {
    grid-column: 3 / 4;
    grid-row: 3 / 4;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}

.side-box-4 {
    grid-column: 3 / 4;
    grid-row: 4 / 5;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}

.side-box-5 {
    grid-column: 3 / 4;
    grid-row: 5 / 6;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}

.side-box-6 {
    grid-column: 3 / 4;
    grid-row: 6 / 7;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}




/* Breakpoints for different screen sizes */

/* For large screens (1920px and above) */
@media screen and (min-width: 1920px) {
    tw-story {
        font-size: 2em;
        line-height: 1.45;
    }
}

/* For medium screens (between 1600px and 1920px) */
@media screen and (max-width: 1920px) and (min-width: 1600px) {
    tw-story {
        font-size: 1.5em;
        line-height: 1.45;
    }
}

/* For smaller desktop screens (between 1280px and 1600px) */
@media screen and (max-width: 1600px) {
    tw-story {
        font-size: 1.2em;
        line-height: 1.45;
    }
}

/* For smaller desktop screens (between 1280px and 1600px) */
@media screen and (max-width: 1200px) {
    tw-story {
        font-size: 1em;
        line-height: 1.45;
    }
}

I think I’ve identified the culprit. When I remove

 display: flex;
    justify-content: center;
    align-items: center;

it works. It seems this is what causes the hiccup. I do not have a solution how center the main div though.

I started with Harlowe, a while ago. Like you, I started doing JavaScript and CSS to control the layout.

It’s been awhile since I used Harlowe so I don’t know if things have changed since 3.3.3 in a significant way, but you are correct in that the <tw-passage> is removed and appended within <tw-story>.

I took a route where I injected my own HTML into the DOM, then moved the <tw-story> tag into my HTML. I’m not saying this will solve your problem, but it may jog something in your mind as to how to solve your issue. I think you and I belong to a mere handful of authors that push Harlowe where it’s not supposed to go. :wink:

https://intfiction.org/t/harlowe-thinking-outside-the-box/61328/14


The one thing that raises a red flag in my mind is that you are using JavaScript code to affect the rendering size. Can CSS alone not solve this issue?

EDIT: I also noticed that you have some missing {} brackets in your CSS.

I removed the… aspect-ratio: 4 / 3; style from your .inner-container properties.

It seems to work, as it’s already declared on the .outer-container.

@HAL9000 DUDE! As someone who’s been following your contributions to Harlowe and learning so much from you over the years (probably my biggest influence next to @Greyelf I have to begin by saying how stoked and absolutely honoured I am by your reply. Without you guys there would’ve never been my first and second game. You really help stretch the boundaries of Harlowe and I’m all in on that :smiley: So thank you!

Also, thank you for your suggestions. I will definitely look into it (incl. the missing brackets). Really interesting post you shared, I will have to dig myself in (unfortunately there’s also life getting in the way, so I have to see when I get to it).

I don’t know if you saw the update, but I did find a culprit, namely

display: flex;
    justify-content: center;
    align-items: center;

When I take that out, I can also take out the javascript out, and it works. What it does not solve is the main container “outer-container” being centered – but I could ultimately live with that, as due to the nature and setting of my game I am considering wrapping it in an electron app.

That’s awesome to hear!

I’m not too sure how you want your template to work in the end, but I took the time to go through your CSS and kind of fine tuned it a bit. I hope I didn’t break something else, but here’s your CSS and the story aligns to the top left. I think that’s what you wanted?

In that link I provided, I do have a section about using the browser’s inspector and that’s how I determined that Harlowe was adding a display: flex; to the <tw-story> tag.


* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html, body {
    height: 100%;
    width: 100%;
    overflow: hidden;
  
  	background: grey;
    font-size: 1.5em;
    font-family: Arial, sans-serif;
    color: white;
  
  	/*display: flex;
    justify-content: center;
    align-items: center;*/
}

tw-sidebar {
  	display: none;
}


tw-story {
    font-size: 1.5em;
  	font-family: Arial, sans-serif;
    /*display: flex;
    justify-content: center;
    align-items: center;*/
  
  	display: block;	/* <== HARLOWE INJECTS "display: flex;" */
  
    height: 100vh;
    overflow: hidden;
    color: white;
    margin: 0;
    padding: 0;
}
  
tw-passage {
	height: 100%;
    margin-left: auto;
    margin-right: auto;
}

p {
    font-size: 1em;
  	line-height: 1.45;
}
  

.outer-container {
    /* Maintain a 4:3 aspect ratio */
    aspect-ratio: 4 / 3;
    width: 100%;
    height: 100%;
    max-width: calc(100vh * 4 / 3);  /* Constrain based on height */
    max-height: calc(100vw * 3 / 4); /* Constrain based on width */
    /*display: flex;
    justify-content: center;
    align-items: center;*/
    background-color: blue;
}


/* Inner container  */
.inner-container {
    aspect-ratio: 4 / 3;
    width: 100%;
    height: 100%;
    max-width: 100%;
    max-height: 100%;
    background-color: transparent;
    display: grid;
    grid-template-columns: 1fr 2fr 1fr;
    grid-template-rows: repeat(6, 1fr);
    gap: 20px;
    padding: 20px;
}


/* Styling the boxes */
.box {
    background-color: none;
}

/* Left column */


.middle-box {
    grid-column: 1 / 3;
    grid-row: 2;
    border: 1px solid white;
    padding: 15px;
    background-color: green;
}

/* Middle column */
.head {
    grid-column: 1 / span 2;
	grid-row: 1 / 2;
    border: 1px solid white;
    padding: 15px 15px 5px 15px;
    background-color: pink;
}



.lower-box {
    grid-column: 1 / 3;
    grid-row: 2 / 7;
  	background-color: pink;
    border: 1px solid white;
}



/* Right column with equal height boxes */

.side-box-1 {
    grid-column: 3 / 4;
    grid-row: 1 / 2;
    padding: 0;
  	border: 1px solid white;
    background-color: pink;
}


.side-box-2 {
    grid-column: 3 / 4;
    grid-row: 2 / 3;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}

.side-box-3 {
    grid-column: 3 / 4;
    grid-row: 3 / 4;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}

.side-box-4 {
    grid-column: 3 / 4;
    grid-row: 4 / 5;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}

.side-box-5 {
    grid-column: 3 / 4;
    grid-row: 5 / 6;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}

.side-box-6 {
    grid-column: 3 / 4;
    grid-row: 6 / 7;
    padding: 0;
    border: 1px solid white;
    background-color: pink;
}




/* Breakpoints for different screen sizes */

/* For large screens (1920px and above) */
@media screen and (min-width: 1920px) {
    tw-story {
        font-size: 2em;
        line-height: 1.45;
    }
}

/* For medium screens (between 1600px and 1920px) */
@media screen and (max-width: 1920px) and (min-width: 1600px) {
    tw-story {
        font-size: 1.5em;
        line-height: 1.45;
    }
}

/* For smaller desktop screens (between 1280px and 1600px) */
@media screen and (max-width: 1600px) {
    tw-story {
        font-size: 1.2em;
        line-height: 1.45;
    }
}

/* For smaller desktop screens (between 1280px and 1600px) */
@media screen and (max-width: 1200px) {
    tw-story {
        font-size: 1em;
        line-height: 1.45;
    }
}

I’m glad i’ve been of some help.

1 Like