Adjust the dimensions of a div using hidden ghost content as the basis

Is there a way to size a <div> element based on ghost content instead of the actual visible content?

For example, can we make the box with content "A" appear as if it contains "BCD"?

.container { display: flex; width: 10em; }
.item { flex-grow: 1; text-align: center; padding: 0.5rem 1rem;
border: solid black 1px; }
<div class="container">
<div class="item" data-ghost-content="BCD">A</div>
<div class="item">B</div>
<div class="item">C</div>
</div>

Please note that the container utilizes a flexbox layout.

Answer №1

Whether your page is built manually or with JS will determine the approach you need to take. If you can incorporate an inline style using a custom property like --char-count, you can utilize the flex shorthand for a more versatile solution:

.item { flex: var(--char-count, 1) } /* falls back to: 1 1 0% */

Avoid using flex-grow in this case, as the desired outcome requires setting the flex-basis specifically to 0%.

One interesting aspect of flexbox is that by adjusting flex-grow values (as seen in the use of flex), the space available will be allocated based on the ratio determined by these values.

Additionally, when utilizing CSS var(.., fallback), the fallback value can also be set to 0 if needed, leading to the default flexbox behavior of flex-grow: 0 for 'unset' items.

.container {
    display: flex;
    width: 10em;
}
.item {
    flex: var(--char-count, 1); /* defaults to 1 if 'unset' */
    text-align: center;
    padding: 0.5rem 1rem;
    border: solid black 1px;
}
<div class="container">
    <div class="item" data-ghost-content="BCD" style="--char-count: 3">A</div>
    <div class="item">B</div>
    <div class="item">C</div>
</div>

Answer №2

Indeed, by setting the additional content to have a visibility: hidden; property, it will occupy space without being displayed:

.container { display: flex; width: 10em; }
.item { flex-grow: 1; text-align: center; padding: 0.5rem 1rem;
border: solid black 1px; }
[data-ghost-content]:after {
  content: attr(data-ghost-content);
  visibility: hidden;
}
<div class="container">
<div class="item" data-ghost-content=BC>A</div>
<div class="item">B</div>
<div class="item">C</div>
</div>

In utilizing this method, the "ghost content" would not duplicate the visible content already present within the element, focusing solely on "BC".

To achieve centered output, one could utilize "ghost" data attributes for ":before" and ":after" as well.

Answer №3

Do you think it's possible to make some adjustments to your layout?

.container { display: flex; width: 10em; }
.item { flex-grow: 1; text-align: center; padding: 0.5rem 1rem;
border: solid black 1px; }
.ghost {
  visibility: hidden;
  height: 0;
}
<div class="container">
<div class="item">
  <div class="item-content ghost">ABC</div>
  <div class="item-content">A</div>
</div>
<div class="item">B</div>
<div class="item">C</div>
</div>

Answer №4

Consider including a .wrapper element in your structure, as shown below:

<div class="container">
  <div class="item" data-ghost-content="BCD">
    <div class="wrapper">A</div>
  </div>
  <div class="item">
    <div class="wrapper">B</div>
  </div>
  <div class="item">
    <div class="wrapper">C</div>
  </div>
</div>

You can then utilize a hidden pseudo-element to contain the ghost content. The main content will be absolutely positioned to avoid occupying any space:

[data-ghost-content]::before {
  content: attr(data-ghost-content);
  visibility: hidden;
}

[data-ghost-content] > .wrapper {
  position: absolute;
}

To maintain text alignment, implement flexbox for the .item elements:

.item {
  display: flex;
  justify-content: center;
}

Give it a try with this example:

.item {
  display: flex;
  justify-content: center;
}

[data-ghost-content]::before {
  content: attr(data-ghost-content);
  visibility: hidden;
}

[data-ghost-content] > .wrapper {
  position: absolute;
}


/* Demo only */

.container {
  display: flex;
  width: 10em;
}

.item {
  flex-grow: 1;
  text-align: center;
  padding: 0.5rem 1rem;
  border: solid black 1px;
}
<div class="container">
  <div class="item">
    <div class="wrapper">E</div>
  </div>
  <div class="item" data-ghost-content="BCD">
    <div class="wrapper">A</div>
  </div>
  <div class="item">
    <div class="wrapper">B</div>
  </div>
  <div class="item">
    <div class="wrapper">C</div>
  </div>
</div>

Answer №5

If you have the ability to make changes to the HTML code, consider adding a <span> tag for the visible content. One suggestion is to utilize CSS grid, which allows elements to be layered on top of each other in terms of background and foreground. Here is an example with comments explaining the code:

.container {
  display: flex;
  width: 10em;
}

.item {
  flex-grow: 1;
  text-align: center;
  padding: 0.5rem 1rem;
  border: solid black 1px;
}

.item[data-ghost-content] {
  display: grid;
  
  place-items: start center;
}

.item[data-ghost-content] > span {
  grid-column: 1;
  grid-row: 1;
}

.item[data-ghost-content]::before {
  content: attr(data-ghost-content);
  grid-column: 1;
  grid-row: 1;
  user-select: none;
  visibility: hidden;
  z-index: -1;
}
<div class="container">
  <div class="item" data-ghost-content="BCD">
    <span>A</span>
  </div>
  <div class="item">
    <span>B</span>
  </div>
  <div class="item">
    <span>C</span>
  </div>
</div>

Check out this JS Fiddle demo.

Additional resources:

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What could be the reason for the array not being sorted correctly in ReactJS, even when it is already sorted by the backend system

I am working with an array that is structured like this: const chapters= [ { index:1, title:'chapter-1', lessons:[] } { index:2, title:'chapter-2', lessons:[] } { index:3, title:'chapter-3', lessons:[] } ] The ar ...

Showing a PDF file within a Bootstrap modal

I'm encountering difficulties with a simple task. My goal is to display a PDF using the HTML <object> tag within a Bootstrap modal. I've put together a Plunkr to illustrate the issue. Essentially, there is a straightforward <object> ...

Top and bottom borders embraced by text: the ultimate header design

I'm looking to create a screen-wide headline with a simple text-logo. The challenge is to make it touch the container's top and bottom borders like this example, including its half-height variations. Upon inspecting the HTML, I noticed that ther ...

Dealing with mistakes in a contact form - Finding the correct function

I developed a form using material-ui in React. I am facing some issues with my submit function. I am using a snackbar to notify the user about the successful submission, as well as a snackbar to alert them about missing required fields. The problem arise ...

How to align horizontal UL navigation utilizing CSS sprite background

After numerous attempts, I am struggling to center a 4 element horizontal list using a sprite image as the li background within the footer div. My CSS and HTML code is as follows: #footer-share-links { width:400px; text-align:center; margin:10 ...

*NgFor toggle visibility of specific item

Here is a snippet of HTML code that I'm working with: <!-- Toggle show hide --> <ng-container *ngFor="let plateValue of plateValues; let i=index"> <button (click)="toggle(plateValue)">{{i}}. {{ btnText }}</button> ...

Order a nested array according to the inner value, using a different array as a reference

Having two arrays at hand, array1 requires sorting based on its inner key, role, as per array2. Despite attempting various solutions, I have hit a roadblock due to my lack of understanding on the necessary steps to proceed. The current output for Array1 i ...

The initial child expands in width according to the content until it reaches the boundaries of the parent, triggering the

My goal is to achieve a layout where the parent container's width can vary. The first child element (red) should expand based on its content until it reaches the end of the parent, at which point text-overflow: ellipses should be applied. The second c ...

The attribute @Validation.For("orderName") is not recognized

Attempting to extract the Order Form from the Bakery Template for use on my website has resulted in an error in the code: "@Validation.For("orderName")" attribute is unknown. <div class="fieldcontainer" data-role="fieldcontain"> ...

Incorporating design library styles (js variables) into my scss documents

I have been tasked with utilizing a custom design library that exports styles, such as fonts and font weights, as JavaScript objects. However, my code base primarily consists of SCSS files. Is there a method to incorporate JavaScript objects into my SCSS f ...

Animation is not applied to Bootstrap Collapse on a row within a table

My Bootstrap 4 table has an issue - when I apply the "collapse" class to a table row, it behaves differently compared to applying it to a div element. Clicking "animate div" smoothly animates the target div, but clicking "animate tr" does not animate the ...

What is the best way to eliminate the default background color applied to the body automatically?

I'm currently developing a Covid-19 tracking web application and I am using chartJS to showcase data from an API. In my CSS, I have assigned a background color to all elements with an asterisk (*), but for some reason there are empty spaces around the ...

Issue with loading 3D model using three.js in a web browser

While using ASP.Net core, I encountered an issue with loading a 3D model using the Three.js library. The error message "ERR_NAME_NOT_RESOLVED" appears when trying to load the scene. You can view the code in my VS View here. This code works perfectly in VS ...

Optimal Strategy: Utilizing Spring Boot for Backend Development and jQuery for Frontend Interface

I am currently tackling a project that involves a Spring Boot 2 Backend and a jQuery Frontend. The frontend communicates with the backend by sending Ajax requests to Spring REST controllers in order to interact with database entities. One of the challenge ...

Adding HTML elements to a button using an array: a step-by-step guide

In the process of developing a web application feature using JavaScript, I have come up with a simple plan: Place a button in the bottom left corner. The button should only become visible after scrolling begins. Upon clicking the button, a new window wil ...

What is the best way to check for changes in value using the onchange

The function is encountering an error and failing to execute. Despite my attempts to check for the onchange property in order to prevent errors, I keep receiving an error message stating "Cannot read property 'onchange' of undefined." Below i ...

Customize Tab indicator styling in Material-UI

Currently, I am attempting to customize the MUI tab by changing the indicator from a line to a background color. Through my research, I discovered that using TabIndicatorProps and setting a style of display:none eliminates the indicator completely. However ...

The Language Switcher is not displaying the new language setting

Starting a fresh website using Nuxt, I am currently in the process of setting it up for multilingual functionality in French and English. For setting up translation and language switcher, I referred to this specific tutorial and implemented the following: ...

Trouble with implementing an onclick event listener in a foreach loop

While generating and adding HTML in a for loop, I noticed that adding onclick events within the same loop is not functioning correctly: items.forEach(item => { itemHtml = `<div class="${item.id}">${item.id}</div>`; $(".it ...

Swap two frames effortlessly with just a single click!

Is there a way to effortlessly change the contents of two frames with just one click? With a single click, I'd like to modify both "framename" and "framename2" by setting their href attribute to 'qwerty' and 'qwerty2' respectively ...