Q:

Why does padding lead to jumpy animation?

Why does the ::before pseudo element jump during a height transition when I apply top and bottom padding to its parent?

a {
  font-size: 2em;
  font-family: sans-serif;
  text-transform: uppercase;
  color: #fff;
  text-decoration: none;
  position: relative;
  /* Removing this padding resolves the animation issue, but why? */
  padding: 1em;
}

a::before {
  content: "";
  width: 0.06em;
  height: 0%;
  position: absolute;
  background: #fff;
  left: 0;
  transition: height 0.25s linear;
}

a:hover::before {
  height: 100%;
  bottom: 0;
}

.container {
  background: #3a3a3a;
  height: 100%;
  display: flex;
  padding-top: 1em;
  justify-content: center;
  align-items: flex-start;
}

body,
html {
  height: 100%;
  margin: 0;
}
<div class="container">
  <a href="#">Hover Me</a>
</div>

A:

If you have padding on an element, then apply position absolute on one of it's children the padding amount will be added as an offset to that child element. 
Say you have padding-top:10px;, it'll become top:10px, i think some browsers do rest this.
DEMO

*,
*:before,
*:after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.test {
  width: 100px;
  height: 100px;
  padding-top: 15px;
  border: 5px solid red;
}

.test>div {
  height: 50px;
  width: 50px;
  border: 5px solid red;
}

.test:hover>div {
  position: absolute;
  /* uncomment this line to see it */
  /* top: 0; */
}
<div class="test">
  <div></div>
</div>

Now to fix your issue.

a {
  font-size: 2em;
  font-family: sans-serif;
  text-transform: uppercase;
  color: #fff;
  text-decoration: none;
  position: relative;
  padding: 1em;
}

a::before {
  content: "";
  width: 0.06em;
  height: 0%;
  position: absolute;
  background: #fff;
  left: 0;
  /* rest the top here */
  top: 0;
  transition: height 0.25s linear;
}

a:hover::before {
  height: 100%;
  bottom: 0;
  /* unsetting the top because top:0 bottom:0; is full heiht which will prevent the animation the way you want it*/
  /* unsetting the top and not the bottom so it goes upward */
  top: unset;
}

.container {
  background: #3a3a3a;
  height: 100%;
  display: flex;
  padding-top: 1em;
  justify-content: center;
  align-items: flex-start;
}

body,
html {
  height: 100%;
  margin: 0;
}
<div class="container">
  <a href="#">Hover Me</a>
</div>

