What methods can be used to restrict the user from typing at the very end of a scrollable textarea?

Hello there, I hope everything is going well for you!

I'm currently working on a project with a basic code editor and trying to find the best way to add some space at the bottom of the textarea. I don't want users to always be typing right at the very bottom when things start to overflow or scroll. It's similar to what CodePen does.

The challenge I'm facing is that I have two divs positioned absolutely side by side - one for line numbers and the other for lines. I've also synchronized their scrolling. Adding extra space on top of that has me stuck!

Here is a mock-up on CodePen that shows my work-in-progress: CodePen: Textarea with Line Numbers

$(document).ready(function() {
  $(".bulk-editor .editor").bind("input propertychange", function() {
    var lineCount = $(this).val().split("\n").length;
    $(".lines").text('');
    for (var i = 0; i < lineCount; ++i) {
      $(".lines").append("<span class='linenum'></span>");
    }
  });

  $('.editor').scroll(function() {
    var top = $(this).scrollTop();
    $('.lines').scrollTop(top);
  });

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

html,
body {
  height: 100%;
}

.container {
  height: 300px;
  padding: 16px 0;
}

.bulk-editor {
  position: relative;
  height: 100%;
  width: 100%;
  counter-reset: matches;
  outline: none;
  font-family: monospace;
  border: 1px solid #ced4da;
  overflow: hidden;
}

.bulk-editor-wrapper {
  position: relative;
  top: 0;
  padding-top: 4px;
  height: 100%;
  width: 100%;
}

.lines {
  position: absolute;
  top: 0;
  left: 0;
  width: 40px;
  height: 100%;
  line-height: 1.2;
  font-size: 1rem;
  user-select: none;
  outline: none;
  border: none;
  z-index: 2;
  background: #e4e4e4;
  overflow: hidden;
  padding-top: inherit;
}

.linenum {
  display: block;
  width: 40px;
  text-align: right;
  color: #808080;
  line-height: inherit;
  font-size: inherit;
  &::before {
    counter-increment: matches;
    content: counter(matches);
  }
  padding-right: 10px;
}

.editor {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  padding-left: 60px !important;
  white-space: pre-wrap;
  outline: none;
  background-color: white;
  border: none;
  resize: none;
  margin: 0;
  color: grey;
  line-height: 1.2;
  font-size: 1rem;
  overflow: auto;
  padding-top: inherit;
  &:focus {
    color: black;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!--Refer to this article https://www.codeproject.com/Tips/5163219/HTML-Line-Numbering-using-textarea -->
<div class="container">
  <div class="bulk-editor">
    <div class="bulk-editor-wrapper">
      <div class="lines"></div>
      <textarea class="editor" rows="10" autocorrect="off" spellcheck="false"></textarea>
    </div>
  </div>
  </div>

https://i.sstatic.net/uPwWA.png

https://i.sstatic.net/PuHwP.png

I'm unsure about the correct approach here. Can this be achieved using just CSS, or will a more complex solution involving JavaScript and scroll events be necessary?

If anyone has encountered a similar issue and knows of a good solution, I would greatly appreciate your insights. Thank you so much!

Answer №1

Begin by setting the desired padding-bottom for both .lines and .editor, for example, 20px;

.lines {
  position: absolute;
  top: 0;
  left: 0;
  width: 40px;
  height: 100%;
  line-height: 1.2;
  font-size: 1rem;
  user-select: none;
  outline: none;
  border: none;
  z-index: 2;
  background: #e4e4e4;
  overflow: hidden;
  padding-top: inherit;
  padding-bottom: 20px;
}

.editor {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  padding-left: 60px !important;
  white-space: pre-wrap;
  outline: none;
  background-color: white;
  border: none;
  resize: none;
  margin: 0;
  color: grey;
  line-height: 1.2;
  font-size: 1rem;
  overflow: auto;
  padding-top: inherit;
  padding-bottom: 20px;
  &:focus {
    color: black;
  }
}

Next, if you are on the last line of the editor, ensure automatic scrolling down.
In the function for the input propertychange event, insert this:

if (this.selectionStart === this.value.length) {
  $(this).scrollTop($(this).prop("scrollHeight"));
}

Answer №2

While working on developing a text editor, I encountered similar challenges. Instead of synchronizing scrolling, I opted to have the textarea automatically expand based on the code length.

function updateSize(){
    var code = document.getElementById("code"); //referring to the textarea
    var codeHighlight = document.getElementById("codeHighlight"); //highlighted code container
    var longestLine = 0;
    for (var i = 0; i < code.value.split("\n").length; i++) {
        if(code.value.split("\n")[i].length > longestLine){
            longestLine = code.value.split("\n")[i].length;
        }
    }
    code.style.width = (longestLine+2) + "ch";
    code.style.height = 13.33333*1.15*(code.value.split("\n").length+1) + "px";

    codeHighlight.style.width = (longestLine+3) + "ch";
    if(longestLine == 0 && code.value.split("\n").length == 1){
        //set default size if no text present
        code.style.width = "100px";
        code.style.height = "100px";
    }
}
document.onkeyup = updateSize();

I placed a smaller textarea over a div containing syntax highlighting. On each keypress by the user, the textarea adjusts its size to fit the text. Additionally, I recommend including the following CSS along with existing styles:

#code{
    outline: none;
    overflow: hidden;
    resize: none;
}

Ensure to target #code in the CSS rules above.

You can view my implementation at this link and also access the script file here. Although not all code may be relevant, focus on the updateHighlight() function and the editMode div section.

I hope this explanation proves beneficial!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Numerous SVGs sharing identical IDs

Is it possible to include multiple SVGs on an HTML page and utilize the same IDs in each of them? <div> <svg height="0" width="0"> <clipPath id="svgPath"> ........ </svg> <svg height="0" width="0"> < ...

Unable to showcase the elements of an array within the AJAX success callback

$.ajax({ type: "GET", url: 'http://localhost/abc/all-data.php', data: { data1: "1"}, success: function(response) { ...

The external embedded CSS seems to be missing from index.html after the Docker build process

My Vue/Webpack application includes an embedded CSS link in my index.html file that references an external source. Here is an example snippet: <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" con ...

Developing a quiz using jQuery to load and save quiz options

code: http://jsfiddle.net/HB8h9/7/ <div id="tab-2" class="tab-content"> <label for="tfq" title="Enter a true or false question"> Add a Multiple Choice Question </label> <br /> <textarea name ...

Struggling with aligning HTML tabs in Django framework

https://i.sstatic.net/vsnqD.pngI have been working on displaying a list of data based on tabs. I have successfully retrieved the data and shown it, but the issue lies in the HTML structure. Certain parts of the HTML should not repeat, but they need to appe ...

Guide on implementing CSS modules in a WordPress plugin built with React

Within one of my tsx files, I included this line: import styles from "../../styles/buyTicket.module.css"; This resulted in the following error message: ERROR in /Applications/MAMP/htdocs/wp-content/plugins/tikex/tikexModule/components/BuyTicket/ ...

Stacked list using IE7 browser compatibility

Currently, I am facing an issue with IE7 where the list appears at the top of the submenu. Is there any solution to bring it back to its intended position? Surprisingly, this problem does not occur in IE8 or higher versions. I would greatly appreciate it i ...

Transmitting a file using Ajax and submitting an input with jQuery

I have a form for uploading a file along with an input field. <form id="uploadForm"> <input type="text" id="name"> <input type="file" id="uploadFile"> </form> Here is the Aj ...

What is the best way to trigger a function when a button is enabled in Angular 8?

Here is a portion of my sign-in.component.html file. I have created a function in the corresponding sign-in.component.ts file that I want to trigger when the button below becomes enabled. Here is an example of what I am trying to achieve: <div class= ...

Different methods for incorporating script-specific data into markup

How can we include extra meta data in HTML code to support client-side javascript functionality? Let's consider some straightforward examples: A list of contacts that, when clicked, displays their location on a map. For instance, how can we link la ...

Different Styles of CSS Borders for List Items

Hey, I'm facing an issue with using borders in list items. I wanted to add borders to all the elements in the <li>, but when the width of the <li> exceeds the window's width, the right side border disappears. How can I resolve this ...

Is it possible to use jQuery sortable and serialize to save data into a

I've nearly completed this project, but I'm stuck on extracting values from the database and properly displaying them within the <li></li> tags in the right order with the correct links. Here's what I have so far: HTML < ...

ID is not receiving the CSS styles

I'm having trouble applying my CSS to a specific img ID element on the page. I've been trying to solve this for about 30 minutes with no luck. The strange thing is, I have two other elements with the same HTML and CSS that are working correctly. ...

When a radiobutton is clicked, a jQuery call to a PHP function triggers an AJAX request which results in a JavaScript function becoming unrefer

Currently, I have a situation where two radio buttons are representing different products. When one of them is clicked, the goal is to update the price displayed on the website based on the selected product. Everything seems to be working fine when using t ...

Issue with implementing custom fonts using @font-face

I've added custom @font-face styling to my CSS using a downloaded font, but it doesn't seem to be working. Below is my CSS code: @font-face { font-family: "Quicksand"; src: url("fonts/Quicksand/Quicksand-Light.otf") format("opentype"); } The f ...

Having trouble getting the CSS footer from cssstickyfooter.com to function properly

I tried implementing some basic CSS from to create a sticky footer that remains at the bottom of the page regardless of content length. However, I am encountering a problem with the footer not behaving as expected. There are actually two issues with the f ...

Animating the mobile menu transition using Bootstrap CSS

Can anyone help me with animating the mobile menu when I click the menu icon? This is what I have for the menu: .overlay-menu { position: fixed; display: none; z-index : 1040; width: 100vw; height: 100vh; background: rgba(0, 0,0, 0 ...

Customizing Bootstrap modal backdrop with CSS

I'm exploring how to achieve the backdrop effect of the Bootstrap modal without actually having to load a modal. However, I'm struggling to make it work correctly. Can anyone provide insight into the CSS that the Bootstrap backdrop utilizes inter ...

Exploring the internet using a specific font style and ensuring a

I am facing an issue with the fonts on my website. They work perfectly in all browsers when using http, but as soon as I switch to https, the fonts stop working in IE8 and lower versions. However, they do display correctly in ie9. When trying to access th ...

The line directly following the first line within the <li> element is located in the same position

I need help with customizing the bullet background-image for an <li> element. I want the text in the bullet to be displayed outside the marker using the CSS property list-item-position: outside. However, my current implementation doesn't seem to ...