Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Need to shrink default textarea size or create an auto-expanding input field with word wrap under repeating sections.

Hi there, I have been working on a custom character sheet for a game I'm making to play with friends. I've run into a lot of snags along the way with the coding and all that, and I've been able to solve most of them by searching through these forums and google search, but I've hit a dead end at this one spot. I've tried many, many different snippets of code and I can't make anything work right here.

So all I want to do is to make a default height for resizable textboxes for a repeating section. The repeating section is super basic, just has an input name, and a box for description to go into. But the default boxes are huge, and only a couple things would actually merit multiple lines. Alternatively, or even better, I'd like to have a section that auto-expands to the size of the text put in. I was able to find a code snippet that expanded horizontally, but not vertically, and text refused to wrap. I don't remember where I found that one, and it is no longer around on my sheet, sorry :(

Anyways, here is the relevant sections of code...

HTML: (The class='sheet-masteries' is for a tabbing function on the sheet.)

<div class="sheet-masteries">
<h2>Masteries</h2>
<h3>Combat Masteries</h3><fieldset class='repeating_masteries1'><input type='text' name='attr_masteryname' class='sheet-long'><textarea name='attr_masterynamedesc'></textarea></fieldset>
<h3>Knowledge Masteries</h3><fieldset class='repeating_masteries2'><input type='text' name='attr_masteryname' class='sheet-long'><textarea name='attr_masterynamedesc'></textarea></fieldset>
<h3>Crafting Masteries</h3><fieldset class='repeating_masteries3'><input type='text' name='attr_masteryname' class='sheet-long'><textarea name='attr_masterynamedesc'></textarea></fieldset>
<h3>Social Masteries</h3><fieldset class='repeating_masteries4'><input type='text' name='attr_masteryname' class='sheet-long'><textarea name='attr_masterynamedesc'></textarea></fieldset>
<h3>Practical Masteries</h3><fieldset class='repeating_masteries5'><input type='text' name='attr_masteryname' class='sheet-long'><textarea name='attr_masterynamedesc'></textarea></fieldset>
<h3>Magic Masteries</h3><fieldset class='repeating_masteries6'><input type='text' name='attr_masteryname' class='sheet-long'><textarea name='attr_masterynamedesc'></textarea></fieldset>
</div>

... ...

<script type="text/worker">
const buttonlist = ["skills","masteries","equipment","biography"];
buttonlist.forEach(button => {
on(`clicked:${button}`, function() {
setAttrs({
sheetTab: button
});
});
});
</script>

CSS:

textarea {
resize:both;
background-color: #4b4b4b;
color: #ececec;
border: 1.25px solid gray;
width: 100%;
}

... ...

input.sheet-long {
vertical-align: top;
width: 150px;
}

... ...

/* Tabs Stuff Here */
/*Configure the tab buttons*/
.charsheet .sheet-skills,
.charsheet .sheet-equipment,
.charsheet .sheet-masteries,
.charsheet .sheet-biography {
display: none;
}

.sheet-rolltemplate-default td {
padding: 1px;
line-height: 1.4em;
vertical-align: top;
}
.sheet-rolltemplate-default {
margin-left: -30px;
margin-right: 20px;
}

/* show the selected tab */
.charsheet .sheet-tabstoggle[value="skills"] ~ div.sheet-skills,
.charsheet .sheet-tabstoggle[value="equipment"] ~ div.sheet-equipment,
.charsheet .sheet-tabstoggle[value="masteries"] ~ div.sheet-masteries,
.charsheet .sheet-tabstoggle[value="biography"] ~ div.sheet-biography {
display: block;
}


Put the tabbing code snippets in just in case they're relevant.

If any HTML/CSS geniuses can help me out, I'd greatly appreciate it. Thank you.

June 25 (1 year ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

You want content scaled inputs (or rather textareas). Essentially just swap all the width scaling stuff for height in the code linked.

I remember seeing that one. I tried it and it almost worked. It didn't actually scale the height, and I suspect the reason is because the text wasn't wrapping. So if I were to use that, how would I make it so the text wrapped?

June 25 (1 year ago)

Edited June 26 (1 year ago)
vÍnce
Pro
Sheet Author

IME, I don't think the autoexpand trick works with textarea. ;-(
Can't you just give your textarea elements a height?  You will probably need to add a class to them and include a little more of the html's hierarchy to help with css specificity.
example(not tested);

<h3>Magic Masteries</h3>
<fieldset class='repeating_masteries6'>    
<input type='text' name='attr_masteryname' class='sheet-long'>
<textarea class="text-tall" name='attr_masterynamedesc'></textarea>
</fieldset>
</div>

.ui-dialog .charsheet .repcontainer textarea.text-tall {
    height: 4em;
    min-height: 4em;
resize:both;
background-color: #4b4b4b;
color: #ececec;
border: 1.25px solid gray;
width: 100%;
}

updated class name to match.


June 25 (1 year ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

Oh, it definitely works with textareas. The piece I forgot to mention is you need to apply whitespace: pre-wrap to the span. I've got a mixin and preset styling in the k-scaffold to use this as easily as possible.

June 25 (1 year ago)

Edited June 25 (1 year ago)
vÍnce
Pro
Sheet Author

That's good to know. I thought there was something like the width worked but the height did not... I'll have to revisit the autoexpand with textareas for sure.

June 26 (1 year ago)

Edited June 26 (1 year ago)
GiGs
Pro
Sheet Author
API Scripter

Vince, you class names don't match there - one is tall-text, the other is text-tall.

Scott, can you post a working version? I assumed it didn't work with textareas too.


Scott C. said:

Oh, it definitely works with textareas. The piece I forgot to mention is you need to apply whitespace: pre-wrap to the span. I've got a mixin and preset styling in the k-scaffold to use this as easily as possible.


I tried this, but it's still not working right... here is what am using...

HTML

<h3>Combat Masteries</h3><fieldset class='repeating_masteries1'><input type='text' name='attr_masteryname' class='sheet-long'><div class="autoExpand"><input type="text" name="attr_masterynamedesc"><span name="attr_masterynamedescb"></span></div></fieldset>

CSS

.autoExpand {
overflow: hidden; /* hides overflow that is caused by the span */
position: relative; /* Allows the input's absolute positioning to be relative to this parent div */
min-width: 100%; /* Whatever feels good to you, prevents a new span from collapsing to 0. */
width: fit-content; /* Will fit the width to the contents without going outside itself or collapsing smaller than its content, though we will be using min-width in the case where there's no content. */
height: fit-content;
}
.autoExpand span {
visibility: hidden;
font-size: 1em;
padding: 0 8px; /* Matching my input's padding so that the widths are correct */
whitespace: pre-wrap;
}
.autoExpand input {
position: absolute; /* removes the input from the DOM flow, allowing the span to exist in the same space */
width: 100%; /* Inputs match the width of the parent element as defined by the spans */
font-size: 1em;
whitespace: pre-wrap;
}

I tried putting "whitespace: pre-wrap;" in both the input and span fields when just the span wouldn't work.

Here's what it looks like right now:

June 26 (1 year ago)

Edited June 26 (1 year ago)
vÍnce
Pro
Sheet Author

@GiGs
Thanks GiGs.  Updated my class name to match.

@Scott
BTW I did a quick test and I cannot get autoexpand to work with textarea height.  Width, yes.

June 26 (1 year ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
I'll post a working version when I'm home this afternoon. I use the technique in pretty much every sheet I've published in the last 3ish years, just need to pull out the exact code.


Scott C. said:

I'll post a working version when I'm home this afternoon. I use the technique in pretty much every sheet I've published in the last 3ish years, just need to pull out the exact code.


Appreciate it much!

Since I've got this post up, would you or anyone else know if it's possible to put these mastery sections in a collapsible section beneath each item in a list of... 20 or so items (skills)? This would be strictly for organizational purposes and it might be a bit more trouble than I think it'd be worth, but would be a nice thing to add on if it's relatively simple.

June 26 (1 year ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

There are several ways to do collapsible sections. The absolutely easiest is to just use the details/summary html tags. A bit more complex is adapting the show/hide areas html and css. I'll post my collapse button construction as well when I do the adaptive textareas.

June 26 (1 year ago)

Edited June 26 (1 year ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

Adaptive Textareas and inputs

Ok, here's my adaptive input/textarea code. I use a modified BEM naming convention for my classes; this makes them look very weird, but relays information about element relationships via the name.

HTML

<div class="adaptive adaptive--input"><!-- Adaptive Input -->
  <span class="adaptive--input__span" name="attr_cost" title="@{repeating_quality_$X_cost}"></span>
  <input class="underlined input-label__input adaptive--input__input" name="attr_cost" type="text" title="@{repeating_quality_$X_cost}"/>
</div>
<div class="adaptive adaptive--text description"><!-- Adaptive Textarea -->
  <span class="adaptive--text__span" name="attr_effect" title="@{repeating_injury_$X_effect}"></span>
  <textarea class="underlined adaptive--text__textarea" name="attr_effect" data-i18n-placeholder="injury effect" title="@{repeating_injury_$X_effect}"></textarea>
</div>

CSS

.ui-dialog .tab-content .charsheet .adaptive {
  display: grid;/* Display grid to easily overlay our span and textarea/input */
  grid-template-columns: auto;
  grid-template-rows: auto;
  grid-template-areas: "content"; /* A content area where everything inside this gets placed */
  position: relative;
}
.ui-dialog .tab-content .charsheet .adaptive > * {
  grid-area: content; /* place all direct children of the adaptive container in the content area */
}
.ui-dialog .tab-content .charsheet .adaptive > span {
  /* Setup the basics for the span. This is essentially what you need for an adaptive input */
  opacity: 0;
  z-index: -10;
  border-width: 1px 3px;/* Make sure that the border and text properties match what is being used for your input or textarea */
  border-style: solid;
  border-radius: 5px;
  border-color: transparent;
  box-sizing: border-box;
  text-transform: initial;
  border-radius: 0px;
}
.ui-dialog .tab-content .charsheet .adaptive--text {
  min-height: 4rem;/* Define a minimum height for the container when it is being used for an adaptive textarea */
}
.ui-dialog .tab-content .charsheet .adaptive--text__span {
  white-space: pre-wrap; /* When the span is being used to make a textarea adaptive, make sure that it allows wrapping of text */
  padding: 2px; /* Give it the same padding as our textarea */
}
.ui-dialog .tab-content .charsheet .adaptive--text__textarea {
  width: 100%;/* Make our adaptive textarea always take up the full space of the container
  height: 100%;
  resize: none;/* because it's adaptive, we don't want this to be resizable */
}
.ui-dialog .tab-content .charsheet .adaptive--text__textarea,
.ui-dialog .tab-content .charsheet .adaptive--input__input {
  position: absolute; /* The textarea or input in the construct is given absolute positioning so it doesn't influence the size of the container */
}
.ui-dialog .tab-content .charsheet .adaptive--input__input {
  width: 100%; /* An input in the adaptive container needs to use all the width available from the container */
}
.ui-dialog .tab-content .charsheet .adaptive--input__span {
  padding: 2px; /* When the span is being used to make an input adaptive, give it the same padding as our inputs and an an appropriate minimum height */
  min-height: 1.5rem;
}

Collapsible containers

And then, for the collapsible sections here's what I use for most projects:

HTML

<div class="collapse-container">
  <input type="checkbox" class="collapse" value="1">
  <!-- Content that should always be displayed -->
  <div class="collapsed">
    <!-- Content that should only be displayed when collapsed -->
  </div>
  <div class="exanded">
    <!-- Content that should only be displayed when expanded -->
  </div>
</div>

CSS

.ui-dialog .tab-content .charsheet input:is([type="checkbox"],[type="radio"]){
  appearance: none; /* Allow us to fully style checkboxes and radios as we please, as if they were divs - Does not work on other types of inputs unfortunately */
}
.ui-dialog .tab-content .charsheet .repitem:hover .collapse,
.ui-dialog .tab-content .charsheet .collapse-container:hover .collapse {
  opacity: 1;
}
.ui-dialog .tab-content .charsheet .repitem .collapse,
.ui-dialog .tab-content .charsheet .collapse-container .collapse {
  opacity: 0;
  position: absolute;
  right: -10px; /* Positioning is what I usually use, but adjust right/top and any other properties below this point as needed for your use case */
  top: 0px;
  border: 0px solid black;
  border-radius: 0;
  color: black;
  text-transform: none;
  background-color: transparent;
}
.ui-dialog .tab-content .charsheet .repitem .collapse:before,
.ui-dialog .tab-content .charsheet .collapse-container .collapse:before {
  /* this version of the collapse uses the pictos font for icons, but you could easily switch it to using material icons or another freely available icon font */
  content: "y";
  font-family: pictos;
}
.ui-dialog .tab-content .charsheet .repitem .collapse:checked,
.ui-dialog .tab-content .charsheet .collapse-container .collapse:checked {
  color: lightgray;
  background-color: transparent; /* I have the collapse button just use the icon font, but you can adjust as needed for your project */
}
.ui-dialog .tab-content .charsheet .repitem .collapse:checked ~ .expanded,
.ui-dialog .tab-content .charsheet .repitem .collapse:checked ~ .collapse-container .expanded,
.ui-dialog .tab-content .charsheet .collapse-container .collapse:checked ~ .expanded,
.ui-dialog .tab-content .charsheet .collapse-container .collapse:checked ~ .collapse-container .expanded {
  display: none !important; /* While !important is usually bad practice, in a case like this where the behavior is supposed to override any other possible behavior, it's good to use it */
}
.ui-dialog .tab-content .charsheet .repitem .collapse:checked ~ .expanded--empty:is(:not([value]), [value=""]) + *,
.ui-dialog .tab-content .charsheet .repitem .collapse:checked ~ .collapse-container ~ .expanded--empty:is(:not([value]), [value=""]) + *,
.ui-dialog .tab-content .charsheet .collapse-container .collapse:checked ~ .expanded--empty:is(:not([value]), [value=""]) + *,
.ui-dialog .tab-content .charsheet .collapse-container .collapse:checked ~ .collapse-container ~ .expanded--empty:is(:not([value]), [value=""]) + * {
  display: none !important;
}
.ui-dialog .tab-content .charsheet .repitem .collapse:not(:checked) ~ .collapsed,
.ui-dialog .tab-content .charsheet .collapse-container .collapse:not(:checked) ~ .collapsed {
  display: none !important;
}
.ui-dialog .tab-content .charsheet .repitem .collapse:hover,
.ui-dialog .tab-content .charsheet .collapse-container .collapse:hover {
  color: black; /* Change the active color of the collapse button to whatever you like */
}

This creates a generic collapse framework that you can use damn near anywhere. It's also preset up to use repitems as a collapse container so you don't have to nest collapse containers inside your repeating section.

June 27 (1 year ago)
vÍnce
Pro
Sheet Author

Nice.  Thanks for posting these Scott.

That's pretty sick, man. Thanks!
June 27 (1 year ago)
GiGs
Pro
Sheet Author
API Scripter

Thank you for posting, Scott.

Can you trim that to include only what is needed for the collapsible text?

June 27 (1 year ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

GiGs said:

Thank you for posting, Scott.

Can you trim that to include only what is needed for the collapsible text?

About the only thing that isn't required there is this:

  border-width: 1px 3px;/* Make sure that the border and text properties match what is being used for your input or textarea */
  border-style: solid;
  border-radius: 5px;
  border-color: transparent;
  box-sizing: border-box;
  text-transform: initial;
  border-radius: 0px;

But, that demonstrates how to copy the styling of your textarea.

Unless you mean only what's required for the expandable textareas? Which would be everything except the last two css declarations:

.ui-dialog .tab-content .charsheet .adaptive {
  display: grid;/* Display grid to easily overlay our span and textarea/input */
  grid-template-columns: auto;
  grid-template-rows: auto;
  grid-template-areas: "content"; /* A content area where everything inside this gets placed */
  position: relative;
}
.ui-dialog .tab-content .charsheet .adaptive > * {
  grid-area: content; /* place all direct children of the adaptive container in the content area */
}
.ui-dialog .tab-content .charsheet .adaptive > span {
  /* Setup the basics for the span. This is essentially what you need for an adaptive input */
  opacity: 0;
  z-index: -10;
  border-width: 1px 3px;/* Make sure that the border and text properties match what is being used for your input or textarea */
  border-style: solid;
  border-radius: 5px;
  border-color: transparent;
  box-sizing: border-box;
  text-transform: initial;
  border-radius: 0px;
}
.ui-dialog .tab-content .charsheet .adaptive--text {
  min-height: 4rem;/* Define a minimum height for the container when it is being used for an adaptive textarea */
}
.ui-dialog .tab-content .charsheet .adaptive--text__span {
  white-space: pre-wrap; /* When the span is being used to make a textarea adaptive, make sure that it allows wrapping of text */
  padding: 2px; /* Give it the same padding as our textarea */
}
.ui-dialog .tab-content .charsheet .adaptive--text__textarea {
  width: 100%;/* Make our adaptive textarea always take up the full space of the container
  height: 100%;
  resize: none;/* because it's adaptive, we don't want this to be resizable */
}
.ui-dialog .tab-content .charsheet .adaptive--text__textarea {
  position: absolute; /* The textarea or input in the construct is given absolute positioning so it doesn't influence the size of the container */
}