+2 votes
by (630 points)
I'm trying to set up a changer variable to quick format specific hooks of text as center aligned, left justified.

Currently, I have these in the Startup passage:

(set: $AlignCenter to (align: "=><="))
(set: $AlignLeft to (align: "<=="))

Then in the story passage, I nest them like so:

$AlignCenter [ $AlignLeft [ This is the text I want to format. ]]

This results in the formatting I'm looking for, but I'm still looking for a quicker way to format on the fly as I write, as this is used so often.  I can't nest the 2 Align variables because of the hook closer needed at the end, and the changer variable fails if I include an incomplete hook opener.

Is there a way to use (print:) combined with (set:), or another combo, to create an elegant method of basically typing:

$IdealFormat [ This is the text I want to format. ]

to get the same result?  

System: MacOS Sierra.  Twine2.1.3 .  Harlowe 2.0.1.

1 Answer

+2 votes
by (159k points)
selected by
Best answer

There is currently a major issue with using styling information stored within story variables to style the content of your passage, the Save system cannot persist the state of any story that contains these types of variables.

You can use a named hook combined with related CSS to get around both the Save issue as well as your aggregating different styling issue.

1. Use a named hook with a meaningful name to indicate which text to style, this example uses the name from your example so it is easier to compare the two.

|idealformat>[This is the text I want to format.]

2. In your Story Stylesheet area use a CSS selector based on the name of the named hook to style the indicated text.

tw-hook[name="idealformat"] {
	display: block;
	max-width: 50%;
	margin-left: auto;
	margin-right: auto;
	text-align: left;


a. You can use your web-browser's built-in Developer Tools to Inspect the HTML being generated by your original example to determine the CSS being generated the (align:) (or any other) macros. That is how I derived the CSS properties in the above example.

b. There are limitations to the names you can assign a named hook, as the code that coverts the TwineScript into HTML will automatically convert those names based on a set of hidden rules. Two of them being: 1. all letters are converted to lowercase; and 2. all dashes are removed.
eg. IdealFormat => idealformat and ideal-format => idealformat


edit: Fixed usage of examine instead of example in solution.

by (1.1k points)
Can the hook be placed in a variable? I'm thinking not, but wanted to be sure.

Also, there are a few "examines" in the answer which I believe are meant to be "examples"
by (159k points)
As far as I know you can't save a hook as the value of a variable.

But even if it could be done you would end up with the same issue of not being able to persist the story's state using the Save System, because that system does not current support variables containing complex data like Changers..
by (630 points)

First off greyelf, thank you so much for your detailed answer.  The CSS solution is very elegant, and works perfectly for this use-case!

I'm not an experienced web developer, I'm learning more about CSS working in Twine than I ever knew before!  That said, while I'm able to implement your suggestion pretty easily in the Twine Story Stylesheet, I'm getting lost in my web browser trying to determine how you pulled that style data using the developer tools.

I'm using Chrome on Mac OS, and when I view Developer Tools, I can find the style data from the overall Story Stylesheet, but I cannot find style data translated from the Twine macros.  Where in the developer console does this data exist?

Regarding your warning about the Save System.  I have a simple Save System in my Story using the following in my Footer passage:

	(css: "font-size: 12px")
	[Bookmark: \
	(link-repeat: "Save")\
	(confirm: "Saving will overwrite any previous bookmarks! Continue?")\
		(if:(save-game: "Slot A"))[(alert: "Saved!")]\
			[(alert: "Could not save. Try turning off Private Browsing.")]\
	(if: (saved-games:) contains "Slot A" )\
		[/ (link-repeat: "Load")[\
		(confirm: "Loading will return you to a previously saved bookmark. This will completely REPLACE current choices and progress in the story!  Continue?")\
			[(load-game: "Slot A")]\

The $AlignRight variable is set in my Startup Passage:

(set: $AlignRight to (align: "==>"))


I tested my story, which has a few examples of styling within Variables, in Chrome on Mac, and I was able to Save and Load the story without error.  Is it possible the problem is fixed??


Thanks again for your detailed help!

by (159k points)

I'm using Windows so the instructions on how to invoke the Inspect context menu item will be slight different for you, I am also using Chrome but the actual HTML should look very similar.

1. I used your example in a passage then viewed the resulting (temporary) story HTML file in my web-browser.

2. I place my mouse cursor over the aligned text output then use the right mouse button to invoke the context menu and select the Inspect menu item. (the name changes slightly between brands.) This results in HTML like the following being highlighted in the Elements panel.

<tw-expression type="variable" name="AlignCenter"></tw-expression>
<tw-hook style="text-align: center; max-width: 50%; margin-left: auto; margin-right: auto; display: block;">
	<tw-expression type="variable" name="AlignLeft"></tw-expression>
	<tw-hook style="text-align: left; display: block;">This is the text I want to format.</tw-hook>

... as you can see the applying of a style related variable results in two HTML elements being generated: a tw-expression and a related tw-hook. Each tw-hook element has the relevant CSS equivalent of the particular align embedded within it's style property. You will also notice that the second set of elements is a child of the first tw-hook element.

3. Using a little HTML knowledge I determine that there is no need for the parent-child tw-hook relationship in this particular case so I flatten that structure and use a single hook in the final solution.

4. I compare the existing CSS for each of the two tw-hook elements and create a final set of property changes, which in this case is most just a merging of the two sets together without the redundant text-align: center part.


RE: Saving. It appears they patched the story format without me noticing.
That being said I still believe it is better to not use variables to style your story because a copy of the known story variable state is associated with each passage within the Story History System, and these type of variables unnecessarily increase the size of each copy of the story state. Which in turn increases the size of each Save because it persists the current History of the story.

by (630 points)
Thank you, this opens up so many possibilities.  Cheers!