Chapter Text
To preface, this workskin was made with a ton of resources and help from the community, and I will be crediting people as I go, but be aware that there are so many more creators that inspired me than I can possibly credit. Be curious, look for other workskins, and most of all, have fun.
I started making a chatfic workskin of my very own months ago, after thinking, "Hey, chatfics are fun, but is there no way to get the pacing right? Scene breaks just can't pull enough weight, and adding timestamps is a pain, and besides, my currently in progress chatfic can't use timestamps for lore reasons..."
I have been on a journey. And I'm going to take you with me all the way back to the start.
I looked at a lot of chatfic workskin tutorials in my process, but the ones that most impressed and inspired me were Texting skin to match light/dark mode by irrationalpie, and deathmistletoe's works in general. (Seriously, their 'changing names' work? Genius.)
So, starting with that and a whole bunch of help and encouragement from the community (special thanks to Charles_Rockafellor), I eventually got:
Press me!
Group chat: Wild Card Support Group
Minato
This is a text message.
This is a text message that doesn't have a fallback class.
Yu is typing...
Yu is typing...
Yu
This is a text message.
This is another text message.
Okay, this might take a while to explain.
First of all, the phone container is straight out of irrationalpie's work. Though modified to increase the width for PC screens a little, without overstepping the boundaries of narrow screens. (That's what 'width: 500px; max-width: 90vw;' is for: 500px can be altered to however wide you want the container to be on PC screens, and it should never exceed the bounds of the mobile viewport.)
#workskin .phone {
width: 500px;
max-width: 90vw;
position: relative;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 1em auto;
border: 2px ridge;
padding: .5em 0;
display: table;
overflow-wrap: break-word;
hyphens: auto;
}
#workskin .phone h3 {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
#workskin .phoneheader {
border-bottom: 2px ridge;
font-weight: bold;
padding-bottom: .5em;
padding-top: .5em;
margin: 0;
text-align: center;
display: block;
overflow-wrap: break-word;
hyphens: auto;
}Simple, but beautiful.
For the longest time I wrapped all of that in a 'flex' div whose CSS looks like this:
#workskin .flex {
position: relative;
display: flex;
flex-direction: row;
justify-content: center;
}The best advice I can give: don't mess with flex. It's not worth it. It's super not worth it.
I did, though, and eventually, finally, I found a better solution: just make the details element flex.
#workskin details.fadedetails {
display: flex;
flex-direction: row;
justify-content: center;
position: relative;
margin-top: 5em;
}Next, the messages' appearance: this is also mostly out of irrationalpie's work, but there are a few more changes here.
#workskin .text {
margin: .5em .5em .5em 1em;
margin-top: 0;
border-radius: 1em;
padding: .5em 1em;
max-width: 90%;
clear: both;
position: relative;
overflow-wrap: break-word;
hyphens: auto;
float: left;
border-top-left-radius: 0.1em;
border-bottom-left-radius: 0.1em;
outline: 2px ridge;
}The original had two classes for messages, to differentiate incoming and outgoing, so if that's what you're after, you know where to look. Me, personally, I like it better (at least for my WIP) when there's no clear POV texter, and so all the messages are on the 'incoming' side. The max-width was expanded, too, since there's no need to see at a glance which side the message is on.
#workskin .username {
padding: .75em 0;
font-size: .75em;
line-height: .75em;
width: fit-content;
display: block;
clear: both;
margin: 0 auto;
margin-left: 0.9em;
padding-bottom: .5em;
text-align: left;
border-bottom: 0.15em solid;
border-left: 0.8em solid transparent;
}
#workskin .username>strong {
font-weight: normal;
}This last bit is making sure that you can bold the usernames with HTML while not changing the ultimate CSS result. This is for the benefit of readers who don't have Creator's Style on(or who downloaded the fic, or whose browser doesn't support CSS, etc.), to make the usernames stand out from the messages. To that end there's also hiddeninfo:
#workskin .hiddeninfo {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}hiddeninfo is for readers who aren't using the workskin, to communicate info that visual CSS might otherwise convey. It also works well for screen reader users, regardless of if they're using the workskin.
#workskin .username+.text {
border-top-left-radius: 1em;
}This bit rounds the top left corner of the text box, but only for the first message in a sequence--the one that comes after the username. Then there are also tails attached:
#workskin .username+.text::before {
content: "";
position: absolute;
top: 0;
width: 0.6em;
height: 1em;
left: -0.7245em;
border-right: 0.1em solid;
border-top-right-radius: 1.25em 0.625em;
}The 'details' element made to look like a button to open the chat with was just me messing around, you can mess with these properties to make it look however you want.
#workskin .fadedetails > summary {
list-style: none;
padding: 0.5em;
cursor: pointer;
border: 2px solid red;
border-radius: 0.3em;
position: absolute;
top: -3em;
}
#workskin .overlay {
position: absolute;
background: rgba(0, 0, 0, 0);
border: 2px solid transparent;
border-radius: 0.3em;
height: 100%;
width: 100%;
top: -0.1em;
left: -0.1em;
}
#workskin:has(.overlay:hover) details.fadedetails summary {
border: 3px solid red;
background: rgba(0, 0, 0, 0.1);
}
#workskin .fadedetails[open] > summary {
border: 3px solid red;
box-shadow: 0px 0px 3px red;
}
#workskin .fadedetails[open] .overlay {
background: rgba(0, 0, 0, 0.2);
}
#workskin .is-typing strong {
font-size: 1.1em;
}#workskin .relatyping {
position: relative;
clear: both;
}
#workskin:has(.fadedetails[open]) .is-typing {
position: absolute;
left: -1em;
}So that's the appearance of the chat, but that's not what you're actually here for, is it? It's time for
The Time Travel
as in traveling forward in time, which we should all be familiar with by now.
How do you make the messages appear after a set time?
Well, first it's important to note that the set time entirely depends on when you open the 'chatroom' (AKA the details element). I see this as an absolute win. The reader can decide for themselves whether they're ready for the messages to start.
This is more or less how that works:
#workskin .visibly {
visibility: hidden;
}
#workskin:has(.fadedetails[open]) .fade-typing {
visibility: visible;
transition: visibility 0s 9999999s;
}
#workskin:has(.fadedetails[open]) .m1 {
visibility: visible;
transition: all 0s linear 2s;
}
#workskin:has(.fadedetails[open]) .m2 {
visibility: visible;
transition: all 0s linear 4s;
}
#workskin:has(.fadedetails[open]) .t1 {
transition: all 5s linear 5s;
}
#workskin:has(.fadedetails[open]) .t2 {
transition: all 2s linear 11s;
}
#workskin:has(.fadedetails[open]) .m3 {
visibility: visible;
transition: all 0s linear 14s;
}
#workskin:has(.fadedetails[open]) .m4 {
visibility: visible;
transition: all 0s linear 17s;
}To start with, visibly is incredibly important. You need to make sure the messages are hidden to start with, so they can later 'transition' into visibility. Probably rename it though. I've gotten attached to the class name, but it really is unnecessarily confusing.
You can see how every m{#} class (a new class for every single message, that's correct) has two numbers associated with it. The first number doesn't matter at all. It represents the time it takes for the transition to complete, but because the visibility property has no 'in between' steps to transition with, it reads every number you put there as a 0.
The second number is the one that matters: that's the transition-delay, AKA how long it takes for the message to show up after opening the details element.
Fairly simple, right? "But Styx," I hear you asking, "what is that shadowy place over there?" That, my friends, is the Typing Indicator. That's the t1, t2, fade-typing, and relatyping I've ignored until this moment.
You don't actually need to understand the typing indicator. I still don't fully understand the typing indicator. You just need to understand a couple critical components:
#workskin:has(.fadedetails[open]) .fade-typing {
visibility: visible;
transition: visibility 0s 9999999s;
}When the details element opens, fade-typing is visible. Technically. It just takes 9999999 seconds to become visible in practice. (Which is to say, it's not visible.) That means that the t{#} classes can work.
#workskin:has(.fadedetails[open]) .t1 {
transition: all 5s linear 5s;
}Specifically when using the typing indicators, both numbers in the 'transition' property do very much matter. The second number is delay, how long it takes for the indicator to become visible. The first number is how long it's visible before it disappears again.
You might also have spotted the class relatyping in that sequence. If not, here it is:
#workskin .relatyping {
position: relative;
}This is the container class for if there are multiple typing indicators in a row, as in when the indicator is blinking. To make sure the blinks show up in the same place as each other, as in the example, and not on separate lines, you need to wrap them in a div with relative positioning and make the positioning of the t{#} classes absolute.
That's the basic structure of the chat. That's not enough for me.
You might be asking, "Hang on, what's this 'fallback' class the message talks about?" Well...
