Home > database >  How to position an element w.r.t an element just like Grammarly button in textboxes?
How to position an element w.r.t an element just like Grammarly button in textboxes?

Time:12-02

Grammarly is somehow able to put its button on the bottom right of text boxes, as shown in the gif. Moreover, the button moves when the textbox moves.

I'm building a chrome extension that puts a similar button on text boxes (bottom-right). I can get hold of the textbox element by listening to focusin event, so this question is about placing a button on that. So far, I'm not able to find the right approach to do that. I'd also prefer to move my button on the left of any existing buttons like Grammarly to avoid overlapping.

enter image description here

CodePudding user response:

Since textarea element can't have a child like a button, you need to make a parent around the textarea which then could hold a button and a textarea. Then you want to make the botton absolute. It would work like the following example:

html:

 <div >
  <textarea></textarea>
  <button></button>
</div>

css:

.wrapper {
    position: relative;
    width: max-content;
  }
  textarea {
    width: 15rem;
    height: 10rem;
  }
  button {
    position: absolute;
    right: 1rem;
    bottom: 1rem;
    width: 1rem;
    height: 1rem;
  }

the parents size is automatic the size of the child. So if you resize the textarea, the div will also be resize. Since the button is placed absolute at the bottom right corner of the div, it will alway move when you resize.

Hope i could help!

CodePudding user response:

On StackOverflow, the textarea is wrapped directly by a div of the same size. The button was placed as a child to the div element, then possibly positioned with simple CSS, e.g. position: absolute; right: 8px; bottom: 8px;.

Obviously however, that's not how all textareas work, so my best solution (which is far from optimal) is to calculate the position of the textarea and place it accordingly. See the example:

const OFFSET = 5;

const button = document.createElement("button");

[...document.getElementsByTagName("textarea")].forEach(textarea => {
  // get the dimensions of each element, then position the buttons accordingly
  const { top, left, height, width } = textarea.getBoundingClientRect();
  const b = button.cloneNode(true);
  document.body.appendChild(b); // it's necessary to first append the element so CSS wil be applied, otherwise the dimensions will be 0
  
  const { width: bWidth, height: bHeight } = b.getBoundingClientRect();
  b.style.top = (
    (
      top   window.scrollY   height
    ) - OFFSET - bHeight
  )   "px";
  b.style.left = (
    (
      left   window.scrollX   width
    ) - OFFSET - bWidth
  )   "px";
  
  // if you want to do stuff with the button relative to that text area
  b.addEventListener("click", () => doSomething(textarea));
});

function doSomething(textarea) {
  console.log(textarea.value);
}
/* just for the demo */
textarea {
  display: block;
}

button {
  color: white;
  background-color: lightgreen;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: none;
  cursor: pointer;
  box-shadow: 1px 1px 2px 0px rgba(0, 0, 0, 0.3);
  
  /* necessary button CSS: */
  position: absolute;
}

html {
  position: relative;
}
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>
<textarea>text...</textarea>

CodePudding user response:

Add a div with your button after the textarea, and use some CSS to position it:

#myScrollContainer {
  height: 150px;
  overflow: auto;
}
#myTextareaContainer {
  width: 300px;
  position: relative;
}
#myTextarea {
  width: 300px;
}
#myOverlay {
  position: absolute;
  right: 25px;
  bottom: 10px;
}
<div id="myScrollContainer">
<div id="myTextareaContainer">
<form>
<textarea rows="5" cols="50" id="myTextarea">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</textarea>
</form>
<div id="myOverlay">
<button>Me!</button>
</div>
</div>
.<br />
(scroll down)<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
The end
</div>

Note that you might want to position the button dynamically based on the visibility of the scrollbar.

  • Related