How to add elements around an already center-justi

2020-05-01 08:43发布

I have created a form with some text elements aligned vertically like so:

Items aligned vertically

They are centered horizontally and vertically on the page using flexbox:

.my-class {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction:column;
}

What I'm trying to do now is maintain this alignment (i.e. keep everything that's on the page already exactly where it is) while adding some elements on either side of the first text box. I tried wrapping everything in a div but since the elements on either side of the text box are not the same width, the text box loses its alignment:

Items out of alignment

As you can see, the long text boxes are now out of alignment. How can I add elements before and after the first text box without moving where it is?

标签: html css flexbox
1条回答
一纸荒年 Trace。
2楼-- · 2020-05-01 08:56

Assuming it is the url/pass/button that are the one's to be centered, and the https/path stick on each side, I would do it like this, where I use a flex row container and pseudo elements to break each group of item into lines of their own.

With this markup one also have full control to move around the items based on screen width's etc.

The 2 main things making this work is the pseudo elements, that, with their full width, force them into rows of their own, and at the same time push content down, together with the order property, enable to position them before the pass and auth respectively.

Stack snippet

.flex {
  display: flex;
  flex-flow: row wrap;
  justify-content: center;     /*  horiz. center items  */
  align-content: center;       /*  vert. center wrapped items  */
  /*align-items: center;*/     /*  vert. center unwrapped items  */
}
.flex div:nth-child(1),
.flex div:nth-child(3) {       /*  https/path item  */
  flex: 1;                     /*  share space left equal  */
}
.flex div:nth-child(2),
.flex div:nth-child(4) {       /*  url/pass item  */
  flex-basis: 300px;           /*  need equal width  */
}
.flex::before {                /*  1st line breaker  */
  content: ''; width: 100%;
  order: 1;
}
.flex div:nth-child(4) {
  order: 2;
}
.flex::after {                 /*  2nd line breaker  */
  content: ''; width: 100%;
  order: 3;
}
.flex div:nth-child(5) {
  order: 4;
}

/*  styling  */
.flex {
  height: 200px;
  border: 1px solid red;
}
.flex span {
  display: inline-block;
  border: 1px solid gray;
  padding: 2px;
  margin: 2px;
}
.flex div:nth-child(2) span,
.flex div:nth-child(4) span {
  width: calc(100% - 10px);
}
.flex div:nth-child(1) {
  text-align: right;
}
<div class="flex">
  <div><span>http(s)</span></div>
  <div><span>url</span></div>
  <div><span>path</span></div>
  <div><span>***</span></div>
  <div><span>authenticate</span></div>
</div>


If the width of the url/pass should scale with parent's width, use percent combined with CSS Calc.

Stack snippet

.flex {
  display: flex;
  flex-flow: row wrap;
  justify-content: center;
  align-content: center;
}
.flex div:nth-child(1),
.flex div:nth-child(3) {
  flex: 1;
}
.flex div:nth-child(2),
.flex div:nth-child(4) {
  flex-basis: 60%;
}
.flex::before {
  content: ''; width: 100%;
  order: 1;
}
.flex div:nth-child(4) {
  order: 2;
}
.flex::after {
  content: ''; width: 100%;
  order: 3;
}
.flex div:nth-child(5) {
  order: 4;
}

/*  styling  */
.flex {
  height: 200px;
  border: 1px solid red;
}
.flex span {
  display: inline-block;
  border: 1px solid gray;
  padding: 2px;
  margin: 2px;
}
.flex div:nth-child(2) span,
.flex div:nth-child(4) span {
  width: calc(100% - 10px);
}
.flex div:nth-child(1) {
  text-align: right;
}
<div class="flex">
  <div><span>http(s)</span></div>
  <div><span>url</span></div>
  <div><span>path</span></div>
  <div><span>***</span></div>
  <div><span>authenticate</span></div>
</div>


Another option would be to keep the initial flex column direction, and with an extra wrapper use absolute positioning for the http(s)/path items.

.flex {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.flex > div:nth-child(-n+2) {
  position: relative;
  width: 60%;
}
.flex div div:nth-child(1) {
  position: absolute;
  top: 0;
  right: 100%;
}
.flex div div:nth-child(3) {
  position: absolute;
  top: 0;
  left: 100%;
}

/*  styling  */
.flex {
  height: 200px;
  border: 1px solid red;
}
.flex span {
  display: inline-block;
  width: calc(100% - 10px);
  border: 1px solid gray;
  padding: 2px;
  margin: 2px;
}
.flex div div:nth-child(1) {
  text-align: right;
}
.flex div div:nth-child(1),
.flex div div:nth-child(3) {
  width: auto;
}
<div class="flex">
  <div>
    <div><span>http(s)</span></div>
    <div><span>url</span></div>
    <div><span>path</span></div>
  </div>
  <div><span>***</span></div>  
  <div><span>authenticate</span></div>
</div>


Updated (based on another question with a similar need)

One can also keep the simpler markup, with no extra wrapper, and use inline-flex combine with making the flex parent also a flex container.

Stack snippet

body {
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
}
.flex {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
}
.flex div:nth-child(2),
.flex div:nth-child(4) {
  width: 300px;
}
.flex div:nth-child(1) {
  position: absolute;
  top: 0;
  right: 100%;
}
.flex div:nth-child(3) {
  position: absolute;
  top: 0;
  left: 100%;
}

/*  styling  */
.flex {
  border: 1px solid red;
}
.flex span {
  display: inline-block;
  width: calc(100% - 10px);
  border: 1px solid gray;
  padding: 2px;
  margin: 2px;
  text-align: left;
}
.flex div div:nth-child(1) {
  text-align: right;
}
.flex div div:nth-child(1),
.flex div div:nth-child(3) {
  width: auto;
}
<div class="flex">
  <div><span>http(s)</span></div>
  <div><span>url</span></div>
  <div><span>path</span></div>
  <div><span>***</span></div>  
  <div><span>authenticate</span></div>
</div>

查看更多
登录 后发表回答