#javascript #html #css
Вопрос:
У меня есть пользовательский веб-компонент, который я пытаюсь создать, который выглядит примерно так, но после перезагрузки страницы я замечаю тонкий белый div в самом низу каждого изображения.
Я замечаю, что получаю желаемый результат (изображение кулака) сразу после сборки Webpack, инициированной сохранением файла javascript этого компонента. Каждый раз, когда я перезагружаю страницу, на экране отображается второе изображение. Что вызывает такое поведение? Я приложу соответствующие части моего кода ниже. (Укладка больших желтых и белых компонентов выполнена для обеспечения конфиденциальности)
FeaturedProjectCard.js
const template = document.createElement('template') template.innerHTML = ` lt;stylegt; .bottomDivider { position: absolute; bottom: 0; width: 75%; height: 1px; margin: 0; background-color: white; } .container { position: relative; width: 1000px; isolation: isolate; } .description { border-radius: 10px; padding: 25px; color: white; background-color: white; } .linksContainer { display: flex; } .linksContainer gt; a { width: 20px; padding: 10px; color: white; transition: color 0.5s; } .linksContainer gt; a:first-child { padding-left: 0; } .linksContainer gt; a:hover { color: yellow; } .projDesc { width: 50%; display: flex; flex-direction: column; pointer-events: none; } .projDesc gt; * { width: fit-content; pointer-events: auto; } .projImage { position: absolute; top: 50%; right: 0; height: 300px; transform: translateY(-50%); background-color: yellow; border-radius: 5px; z-index: -1; } .projImage gt; img { height: inherit; border-radius: inherit; filter: grayscale(100%); -webkit-filter: grayscale(100%); opacity: 0; transition: opacity 0.5s, filter 0.5s, -webkit-filter 0.5s; } .projImage gt; img:hover { opacity: 1; filter: grayscale(0%); -webkit-filter: grayscale(0%); } .projectHeading { margin: 10px 0; color: yellow; font-size: 12pt; } .projectName { display: inline; margin: 15px 0; font-size: 21pt; color: white; } .softwareContainer { margin: 25px 0 10px 0; color: white; } .softwareContainer gt; span:not(:last-child) { padding-right: 30px; } lt;/stylegt; lt;div class="container"gt; lt;div class="projDesc"gt; lt;span class="projectHeading"gt;Recent Projectlt;/spangt; lt;span class="projectName"gt;lt;/spangt; lt;div class="description"gt;lt;/divgt; lt;div class="softwareContainer"gt;lt;/divgt; lt;div class="linksContainer"gt;lt;/divgt; lt;/divgt; lt;div class="projImage"gt; lt;imggt; lt;/divgt; lt;p class="bottomDivider"gt;lt;/pgt; lt;/divgt; ` class FeaturedProjectCard extends HTMLElement { constructor() { super() //Enable shadow DOM this.attachShadow({ mode: 'open' }) this.shadowRoot.appendChild(template.content.cloneNode(true)) //Insert project image this.shadowRoot.querySelector('img').src = this.getAttribute('image') //Insert project heading this.shadowRoot.querySelector('.projectName').textContent = this.getAttribute('heading') //Insert project description this.shadowRoot.querySelector('.description').innerHTML = //Get description text //Insert software array const softwareItems = //Get items if(softwareItems) { const softwareContainer = this.shadowRoot.querySelector('.softwareContainer') for(let i = 0; i lt; softwareItems.length; i ) softwareContainer.innerHTML = `lt;spangt;${softwareItems[i].textContent}lt;/spangt;` } //Insert link array const links = //Get links if(links) { const linksContainer = this.shadowRoot.querySelector('.linksContainer') for(let i = 0; i lt; links.length; i ) { linksContainer.innerHTML = `lt;a target="_blank" href="${links[i].getAttribute('target')}"gt;${links[i].innerHTML}lt;/agt;` } } //Handle reverse attribute if(this.hasAttribute('reversed')) { this.shadowRoot.querySelector('.bottomDivider').style.right = 0; this.shadowRoot.lastElementChild.style.height = `${this.shadowRoot.lastElementChild.offsetHeight}px` const projDesc = this.shadowRoot.querySelector('.projDesc') const projImage = this.shadowRoot.querySelector('.projImage') const softwareItems = Array.from(this.shadowRoot.querySelectorAll('.softwareContainer gt; span')) projDesc.style.position = 'absolute' projDesc.style.right = '0' projDesc.style.left = 'auto' projImage.style.left = '0' projImage.style.right = 'auto' projDesc.style.alignItems = 'flex-end' softwareItems.splice(0, 1)[0].style.padding = '0' const padding = getComputedStyle(softwareItems[0]).getPropertyValue('padding-right') softwareItems.forEach(item =gt; { item.style.paddingLeft = padding item.style.paddingRight = '0' }) } //Clear markup this.innerHTML = null } } window.customElements.define('featured-project-card', FeaturedProjectCard)
Я использую эти компоненты в HTML со следующим синтаксисом.
lt;featured-project-card class="" reversed image="/something.png" heading="Heading"gt;
Я думаю, что основной причиной такого поведения является включение необязательного атрибута «обратный». На другие компоненты, которые не используют этот атрибут, эта проблема не влияет, так div.projDesc
как имеет position: static
для этих экземпляров. Это позволяет div.container
изменять размер. На этих изображениях показан единственный компонент, в котором используется этот атрибут. Я закончу этот пост одним окончательным изображением компонента без атрибута «обратный» для справки. По сути, я добиваюсь обратного эффекта, задавая div.projDesc
свойства position
, right
, и left
absolute
, 0
, и auto
соответственно. Следовательно, мне пришлось установить div.container
высоту, равную той, какой она была до этих изменений. В противном случае элемент не будет иметь правильного размера, так как position: absolute
используется на единственном дочернем элементе с position: static
Я использовал сервер ResizeObserver, чтобы проверить, не изменял ли div.projDesc
он размер сам по себе более одного раза, и это действительно было так. Чтобы завершить, «перевернутый» div.projDesc
странно изменяет размер (вероятно, из-за того, как обрабатывается атрибут «обратный»), в отличие от не «перевернутых» элементов. Я знаю, что может быть более простой способ решить эту проблему, и я открыт для предложений, однако я хотел бы определить источник такого поведения в надежде лучше понять нюансы HTML, CSS и JS. Я более чем счастлив разъяснить себя любому, кто готов протянуть руку помощи. Заранее благодарю вас!
Не обращенный компонент
Комментарии:
1. Удалите все абсолютные позиции в вашем компоненте, они вам здесь не нужны. Это приведет только к ошибкам (как вы описали) Также для «обратного» абсолютного позиционирования не требуется. Не используйте
lt;pgt;
для создания границ, используйте границу или :после из CSS. Используйте flexbox (или сетку), чтобы получить свой макет.2. Спасибо за комментарии! В настоящее время я нахожусь в процессе преобразования в гибкий макет. Я думаю, что это значительно сократит мой код. Я совершенно забыл о псевдоэлементах, которые, думаю, я тоже включу. Еще раз спасибо, что протянули мне руку помощи.