0

I am trying to have a triangle/arrow at the right of arrow-td. Initial plot with the code below works but the triangle/arrow doesn't scroll with its container arrow-td.

How could I keep the triangle positioned relative to arrow-td even when the user scrolls through main-div?

NOTE: The arrow should stay outside (just right) of main-div. Adding position: relative to arrow-td won't work as that would force arrow to be inside of main-div since overflow-y: auto is activated on main-div.

Check out the plunker

HTML

<div class="main-div">
        <table>
          <tbody>
            <tr>
              <td>Hello</td>
            </tr>
            <tr>
              <td>Hello</td>
            </tr>
            <tr>
              <td class="arrow-td">
                <div class="left-of-arrow">With arrow</div>
                <div class="arrow"></div>
              </td>
            </tr>
            .........
          </tbody>
        </table>
    </div>

CSS

.main-div{
  height: 200px;
  width: 200px;
  overflow-y: auto;
}

table{
    width: 100%;
    max-width: 100%;
}

td{
  width: 100%;
  background-color: #eee;
  display: flex;
}

td>div{
  display: flex;
}

.arrow{
  right: 300px;
  position: absolute;
  width: 0;
  height: 0;
  border-top: 12px solid transparent;
  border-bottom: 12px solid transparent;
  border-right: 12px solid red;
}
Shyamal Parikh
  • 2,988
  • 4
  • 37
  • 78

3 Answers3

2

Isn't possible to your arrow track your td without adding a position relative and changing you main-div width to 100% and setting a size to your table, like I did on that plunker

See my Plunker


To do what you wan't you'll need to add a JavaScript function to track the offset of that td every time you scroll the page, and setting the top property of your arrow.


EDIT: I wasn't in home yesterday, so, I couldn't write a code to solve your issue. I saw your code and there is some issues on your approach. I can't comment there because I don't have karma. But I did some comments on that fork, explaining why those approaches aren't that good.

Updated Plunker

  • Nope, that won't work. `Table` must have the same width as `main-div`. – Shyamal Parikh Jan 19 '16 at 20:41
  • 1
    So, that's not possible without javascript to track your scroll. I'd updated my answer. – Felipe Ramos Jan 19 '16 at 20:50
  • Thanks, but let me explain why your suggestion may not work: 1. Offset gives position relative to doc however, the example I showed in plunker is a part of my html and is within another container with `position: relative`. Which means I have to find position relative to this container and not the doc. 2. Regarding `Scroll` monitoring. The table elements may be deleted dynamically depending on `angular events`. Hence I choose to use `interval` 3. wrt `ele.show() ele.hide()`, Initially, I implemented the same but that conflicts with `ng-show` of angular hence shifted to use `visibility` – Shyamal Parikh Jan 21 '16 at 07:43
  • Regarding `heightLimit -25` I agree, will try to implement it better. – Shyamal Parikh Jan 21 '16 at 07:45
  • 1
    Oh I see, so the DOM changes on angular events and you lose your event. My concern about `setInterval` is, mainly about memory consumption. I hope not but it can slow down your application, even with you verification on arrow and element's top. Can you use a customEvent call when angular events changes it and you lose your scroll monitoring? Maybe, something like that ---> [CustomEvent](https://plnkr.co/edit/CzYXctWW0owkiizzjXZJ?p=preview) – Felipe Ramos Jan 21 '16 at 18:53
0

You have your .arrow set with position absolute, meaning it will not be relative to any scrolling you do unless you explicitly specify it to be.

So, by adding position: relative to your .main-div, you will achieve the arrow moving relative to the .arrow-td.

Where your design fails in look and feel is on the .main-div itself. It has a fixed width of 200px. This may be intentional but for your purposes of having the arrow sit outside the table, it will just not be possible using the current HTML structure you have.

One thing you can do is play with how overflow works for your type of problem.

I decided to take a swing at implementing a solution which is what you see below... however the final implementation is truly up to you! I also put in comments a second version of how this could look, in the CSS named Example #2 give it a try :-)

.wrapper {
  overflow-y: auto;
  width: 335px; /* Example #2: change this to: 100% for a different visual effect */
}

.main-div {
  height: 200px;
  width: 100%; /* Example #2: change this to 200px for a different visual effect */
}

table {
  width: 100%;
  max-width: 100%;
}

td {
  width: 100%;
  background-color: #eee;
  display: flex;
}

td > div {
  display: flex;
}

.arrow {
  left: 300px;
  position: absolute;
  width: 0;
  height: 0;
  border-top: 12px solid transparent;
  border-bottom: 12px solid transparent;
  border-right: 12px solid red;
}

.arrow-td {
  position: relative;
}
<div class="wrapper">
  <div class="main-div">
    <table>
      <tbody>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td class="arrow-td">
            <div class="left-of-arrow">With arrow</div>
            <div class="arrow"></div>
          </td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
        <tr>
          <td>Hello</td>
        </tr>
      </tbody>
    </table>
  </div>
</div>
Community
  • 1
  • 1
AGE
  • 3,752
  • 3
  • 38
  • 60
  • Yes, `main-div` and `table` width are indeed intentional. If I don't get an answer to this question by tomorrow I would either have to implement `javascript` method as @Felipe suggested or change HTML structure as you suggest. – Shyamal Parikh Jan 19 '16 at 21:01
  • @ShyamalParikh you are simply implementing this idea incorrectly, because of your need to use `position: absolute` on your arrow. If you perhaps set the `:after` or `:before` attribute of your `.arrow-td` to contain the arrow as a background image, then you would achieve a similar effect without complicating yourself over `.arrow` – AGE Jan 19 '16 at 21:08
  • But then the background image would again be within `main-div` no? – Shyamal Parikh Jan 19 '16 at 21:14
  • It would be great if you can suggest an example with any image. I too will try this out on my side. – Shyamal Parikh Jan 19 '16 at 21:18
  • @ShyamalParikh sadly I don't, you can only experiment and if you cannot find a solution, you may be forced to reconsider your implementation altogether. Not to panic, perhaps its for the best :) – AGE Jan 19 '16 at 21:21
  • :) Why panic, there is still javascript way through which I can achieve the result I need. Thanks anyways. – Shyamal Parikh Jan 19 '16 at 21:24
  • @ShyamalParikh now that we have narrowed it down, try rethinking and asking this question with a JS approach, that is if you need the help... good luck! – AGE Jan 19 '16 at 21:25
0

This is how I solved the problem through javascript:

I simply track arrow-td's top position, if it is changed .arrow div's top position should also be modified accordingly.

Check out the PLUNKER

Code:

$(document).ready(function(){
  setInterval(function(){
    var heightLimit = $(".main-div").height();
    var parentTop = $(".arrow").parent().position().top;
    var arrowTop = $(".arrow").position().top;
    //Change arrow top position only if parent's position has been changed
    if(arrowTop != parentTop){
      if(parentTop < 0 || parentTop > heightLimit -25){
        $(".arrow").css("visibility","hidden");
      }
      else{
        $(".arrow").css("visibility","visible");
        $(".arrow").css("top",parentTop);
      }
    }
  },500);

});
Shyamal Parikh
  • 2,988
  • 4
  • 37
  • 78