-3

Our webshop generates an invoice based on the the fields that the customers enter. However, not all fields are required. There is one field that is not required, the company name, that we want to be placed above the name + address when applicable.

Currently, the positioning for our additional fields is edited like this:

  /*  .additional-information {
  position: absolute;
  left: 250px;
  bottom: -100px;
  }*/
      .additional-information > div:nth-of-type(1) {
  position: relative;
  left: 0px;
  top: -15px;
}
    .additional-information > div:nth-of-type(2) {
  position: relative;
  left: 0px;
  top: -15px;

#and so forth for a max of 12 fields
}

Is there a way to specifically edit this company field, when a customer entered one? When I inspect the template, I only see a list of '<div>'s, and no identifier for the 'company name' field. I am new to CSS so I might overlook things.

Extra information:

This document is generated by a rental software program. The program does not allow us to customize the HTML code. The only option we have is to add custom CSS so we can edit what is given to us. I have included an example below of our current situation.

The fields are automatically placed under the 'additional-information' class. The company field name falls under <strong>Company name</strong> when applicable, so if a customer has a business, otherwise this field will not show up.

<div class="additional-information">
<div>
   <strong>Company name</strong>
   <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured= "true">...</span>
 </div>
<div>...</div>

The desired end result for the field below:

enter image description here

TvCasteren
  • 449
  • 3
  • 18
  • 1
    Can you add more information ? – Suresh Jun 20 '23 at 19:40
  • to change the location of the company name, you must add your html/template code. However, I think that you'll have to change the code that is used to generate this template to produce this **company name** field before the other ones. – ZombieChowder Jun 20 '23 at 19:42
  • 1
    What does that part of your template HTML look like? – imvain2 Jun 20 '23 at 19:43
  • I added the extra information. Unfortunately this rental software does not allow the user to edit the HTML code, only CSS. – TvCasteren Jun 20 '23 at 20:20
  • 5
    Please read [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask), especially the part about "Help others reproduce the problem" and "DO NOT post images of code" – Tim R Jun 21 '23 at 02:35
  • 2
    @TvCasteren Which is the company name (I don't speak Dutch)? Where is this name stored in the code, and where do you want it to be placed? Can you draw on the image to show us where you want the company name to be placed? Also, add the code, not an image of the code. Please tag me in your comment so that I'll see it when you reply. – Rok Benko Jun 21 '23 at 13:27
  • 1
    We need more information here, but most likely the answer is no you cannot do this unless you have access to JavaScript. – TylerH Jun 21 '23 at 18:55
  • @RokBenko I edited the post. – TvCasteren Jun 21 '23 at 18:56
  • @TylerH that could very well be the answer. – TvCasteren Jun 21 '23 at 18:57

3 Answers3

2

With the help of a screenshot you added before you edited the question, I was able to come up with a solution.

Problem

The problem is that the element with the company name is not a child or descendant of the element where you want to place it. Consequently, using position: absolute; only on the element containing the company name will result in the following output:

Screenshot 1

.additional-information div:first-child {
  position: absolute;
}
<div id="user-info">
  <strong class="customer-name">Sjors</strong>
  <form>
    <div class="show-user">
      <i class="icon-pencil"></i>
      <span>
        "twist"
        <br>
        "5099XX Amsterdam NL"
      </span>
    </div>
  </form>
  <div class="customer-email">johndoe@hotmail.com</div>
  <div class="additional-information">
    <div>
      <strong>Company name</strong>
      <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Testcompany</span>
    </div>
    <div>Second</div>
    <div>Third</div>
    <div>Fourth</div>
    <div>Fifth</div>
    <div>Sixth</div>
  </div>
</div>

Solution

Anyway, there's a CSS solution that is not very elegant. Using position: absolute; also on the parent of the element containing the company name will result in the following output (i.e., a complete mess):

Screenshot 2

.additional-information {
  position: absolute;
  top: 0;
}

.additional-information div:first-child {
  position: absolute;
}
<div id="user-info">
  <strong class="customer-name">Sjors</strong>
  <form>
    <div class="show-user">
      <i class="icon-pencil"></i>
      <span>
        "twist"
        <br>
        "5099XX Amsterdam NL"
      </span>
    </div>
  </form>
  <div class="customer-email">johndoe@hotmail.com</div>
  <div class="additional-information">
    <div>
      <strong>Company name</strong>
      <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Testcompany</span>
    </div>
    <div>Second</div>
    <div>Third</div>
    <div>Fourth</div>
    <div>Fifth</div>
    <div>Sixth</div>
  </div>
</div>

Using some margins will result in the following output:

Screenshot 3

form {
  margin-top: 30px;
}

.additional-information {
  position: absolute;
  top: 0;
}

.additional-information div:first-child {
  margin-top: 32px;
}

.additional-information div:nth-child(2) {
  margin-top: 80px;
}
<div id="user-info">
  <strong class="customer-name">Sjors</strong>
  <form>
    <div class="show-user">
      <i class="icon-pencil"></i>
      <span>
        "twist"
        <br>
        "5099XX Amsterdam NL"
      </span>
    </div>
  </form>
  <div class="customer-email">johndoe@hotmail.com</div>
  <div class="additional-information">
    <div>
      <strong>Company name</strong>
      <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Testcompany</span>
    </div>
    <div>Second</div>
    <div>Third</div>
    <div>Fourth</div>
    <div>Fifth</div>
    <div>Sixth</div>
  </div>
</div>

Edge cases

So far, so good. But there are at least three edge cases you'll need to think of when adapting my solution to your project:

Edge case #1: No company name entered

See the snippet below for a solution.

form {
  margin-top: 30px;
}

.additional-information {
  position: absolute;
  top: 0;
}

.additional-information div:first-child {
  margin-top: 32px;
  border: 1px solid red;
}

.additional-information div:first-child:empty {
  margin-top: 40px;
  border: 1px solid blue;
}

.additional-information div:nth-child(2) {
  margin-top: 80px;
}
<div id="user-info">
  <strong class="customer-name">Sjors</strong>
  <form>
    <div class="show-user">
      <i class="icon-pencil"></i>
      <span>
        "twist"
        <br>
        "5099XX Amsterdam NL"
      </span>
    </div>
  </form>
  <div class="customer-email">johndoe@hotmail.com</div>
  <div class="additional-information">
    <div></div>
    <div>Second</div>
    <div>Third</div>
    <div>Fourth</div>
    <div>Fifth</div>
    <div>Sixth</div>
  </div>
</div>

Edge case #2: Very long company name

If the company name is very long, you'll need to adjust the CSS.

Edge case #3: Default CSS might cause conflicts with my solution

My solution might not work in your project because of the default CSS that comes with the rental software program you mentioned.

My advice

As you can see, it's impossible to come up with an elegant CSS-only solution, ceteris paribus (i.e., all other things being equal). If I were you, I would leave it as is. It might not be perfect in your eyes as is, but I don't think it's worth risking such edge cases to make your clients (or whoever will see it) say: Aw, this looks terrible. It's a trade-off. It might look a little bit better in x% of the cases, but those y% might be way worse.

Rok Benko
  • 14,265
  • 2
  • 24
  • 49
-1

Before reading my proposed solution, please note that while you specificed:

"This document is generated by a rental software program. The program does not allow us to customize the HTML code."

My solution will only work if you can somehow modify the program to always render the company name field, even if it's empty. I am not sure if that counts as "customizing the HTML code".

Also, the HTML template must always generate the same layout with the exact same order of the fields - but I'm assuming it already does that?

The reasoning behind this is if the company field is also generated, even if it's empty, you can control your CSS selectors 100% accurately.

Looking at the HTML template, it seems like the company field is the third <div> of the .additional-information-element. Knowing this, you can use nth-of-type(3) to select that field:

.additional-information > div:nth-of-type(3) { }

Furthermore, we can use a combination of :has() and :empty (or :blank) to select the company field if its empty. If its empty, give it display: none:

.additional-information > div:nth-of-type(3):has(span:empty) {
  display: none;
}

If its not empty, apply your desired positioning values:

.additional-information > div:nth-of-type(3) {
  top: 10px;
  position: absolute;
}

The problem is now that the <div>s are going to overlap each other:

.additional-information > div > span {
  display: block;
}

.additional-information > div:nth-of-type(1) {
  position: relative;
  left: 0px;
  top: -15px;
}

.additional-information > div:nth-of-type(2) {
  position: relative;
  left: 0px;
  top: -15px;
}

.additional-information > div:nth-of-type(3):has(span:empty) {
  display: none;
}

.additional-information > div:nth-of-type(3) {
  top: 10px;
  position: absolute;
}
<div class="additional-information">
  <div>
    <strong>Address</strong>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Address line 1</span>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Address line 2</span>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Address line 3</span>
  </div>
    <div>
    <strong>Phone number</strong>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">12345678</span>
  </div>
  <div>
    <strong>Company name</strong>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Name of company</span>
  </div>
</div>

To prevent this, apply a margin-top value to the first <span> inside the address field, equivalent to the height of 2 lines of text ("Company name" and the company name itself):

.additional-information > div:nth-of-type(1) span:first-of-type {
  margin-top: 35px;
}

And to prevent a margin-top value if the <span> is empty, use a nasty combination of :has() and :empty again:

.additional-information:has(div:nth-of-type(3) span:empty) > div:nth-of-type(1) span:first-of-type {
  margin-top: 0;
}

The code in action

body {
  display: flex;
  gap: 100px;
}

.additional-information > div > span {
  display: block;
}

.additional-information > div:nth-of-type(1) {
  position: relative;
  left: 0px;
  top: -15px;
}

.additional-information > div:nth-of-type(2) {
  position: relative;
  left: 0px;
  top: -15px;
}

.additional-information > div:nth-of-type(3):has(span:empty) {
  display: none;
}

.additional-information > div:nth-of-type(3) {
  top: 10px;
  position: absolute;
}

.additional-information > div:nth-of-type(1) span:first-of-type {
  margin-top: 35px;
}

.additional-information:has(div:nth-of-type(3) span:empty) > div:nth-of-type(1) span:first-of-type {
  margin-top: 0;
}
<div class="additional-information">
  <div>
    <strong>Address</strong>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Address line 1</span>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Address line 2</span>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Address line 3</span>
  </div>
    <div>
    <strong>Phone number</strong>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">12345678</span>
  </div>
  <div>
    <strong>Company name</strong>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Company name</span>
  </div>
</div>



<div class="additional-information">
  <div>
    <strong>Address</strong>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Address line 1</span>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Address line 2</span>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">Address line 3</span>
  </div>
    <div>
    <strong>Phone number</strong>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true">12345678</span>
  </div>
  <div>
    <strong>Company name</strong>
    <span data-private="true" data-openreplay-masked="true" data-openreplay-obscured="true"></span>
  </div>
</div>

Additional info:

Sigurd Mazanti
  • 2,098
  • 1
  • 8
  • 24
-2

Edit: This solution of positioning "the company name, that we want to be placed above the name + address" answered the question as it was presented at the time, that gave only a screenshot of a portion of the markup, showing only <div>..</div> for the section in question and didn't include what happens when the company name isn't given (is the div blank or non-existent?) Yet, people decided to downvote this without even saying why they think it is unhelpful.


If the company name is in the second child div of <div class="additional-information">, perhaps this method will work for you.

#user-info {
  position: relative;
  padding-top: 1em;
  }

.additional-information > div:nth-of-type(2) {
  position: absolute;
  top: 0;
  }
<div id="user-info">
  <strong>Sjors</strong>
  <form>twist</form>
  <div class="customer-email">johndoe@hotmail.com</div>
  <div class="additional-information">
    <div>Phone</div>
    <div>Bedrijfsnaaam (Company Name)</div>
    <div>Straatnaam (Street Name)</div>
  </div>
Tim R
  • 2,622
  • 1
  • 3
  • 19