2015-04-26 48 views
5

我想直觀地突出顯示一組共享相同屬性的同級元素。如何繪製圍繞某些兄弟HTML元素的框?

#boxed_contents span[data-boxme] { 
 
    display: inline-block; 
 
    border: 2px solid #00F; 
 
    border-radius: 5px; 
 
}
<div id="boxed_contents"> 
 
    <span>hello</span><!-- 
 
--><span>world</span><!-- 
 
--><span data-boxme>look</span><!-- 
 
--><span data-boxme>at</span><!-- 
 
--><span data-boxme>me</span> 
 
</div>

幾乎作品就像我想讓它,但我想加盟箱子周圍每個boxme元素,只留下一個框周圍的所有三個要素。我知道我可以將相鄰的boxme元素包裝在一個包裝div中,但是由於這在概念上是一種可視化(而不是結構性)選擇,我真的很想在不修改HTML的情況下做到這一點。

有沒有辦法在純CSS中做到這一點?如果失敗了,加上一些簡單的Javascript?

+0

爲什麼你的元素不能被後面的代碼放在一個'span'中? – bytecode77

+0

@bytecode77他們每個人都需要在一個單獨的跨度,因爲我需要處理每個跨度上的點擊事件。 – user108471

+0

這不一定是一個純粹的設計決定。 CSS圍繞頁面的邏輯HTML結構工作。儘管對這個特定問題(@Hashem Qolami)有一個純粹的CSS答案,但我認爲圍繞內容的包裝div有助於解釋內容在邏輯上是分組的。 – smcjones

回答

1

感謝哈希姆爲把我在正確的軌道上與兄弟選擇(連續的獨特風格元素),和一個僞選擇添加邊框的元素。

我不得不添加一行JavaScript以確保在最後沒有boxme屬性的元素有空白span。通過這樣做,我可以在boxme元素後面的任何非boxme元素上使用:before僞元素。這個策略的主要優點(與Hashem給出的策略相比)是我可以保留原始CSS的圓角。

document.getElementById('boxed_contents').appendChild(document.createElement('span'));
#boxed_contents span[data-boxme] { 
 
    border: 2px solid #00F; 
 
    border-right: none; 
 
    border-radius: 5px 0 0 5px; 
 
    padding-left: 4px; 
 
} 
 
#boxed_contents span[data-boxme] + span[data-boxme] { 
 
    border-left: none; 
 
    border-radius: 0; 
 
    padding-left: 0; 
 
} 
 
#boxed_contents span[data-boxme] + span:not([data-boxme]):before { 
 
    content: ""; 
 
    border: 2px solid #00F; 
 
    border-left: none; 
 
    border-radius: 0 5px 5px 0; 
 
    padding-right: 4px; 
 
}
<div id="boxed_contents"> 
 
    <span>hello</span><!-- 
 
--><span>world</span><!-- 
 
--><span data-boxme>look</span><!-- 
 
--><span data-boxme>at</span><!-- 
 
--><span data-boxme>me</span> 
 
</div>

我不知道該解決方案平臺跨如何,但似乎到Chrome瀏覽器的我的目標平臺上很好地工作。

-1

我編輯了您的代碼,用於描述您希望它的工作方式,類元素中的.boxme標籤應用boxme類位於#box_contents標籤內的樣式。

#boxed_contents.boxme { 
    display: inline-block; 

} 
#boxed_contents.borderBox { 
border: 2px solid #00F; 
     border-radius: 5px; 
} 

:)

<div id="boxed_contents"> 
     <span>hello</span> 
     <span>world</span> 
<div class='borderBox'> 
     <span class='boxme'>look</span> 
     <span class='boxme'>at</span> 
     <span class='boxme'>me</span> 
    </div> 
</div> 

如果您知道boxme結構的佈局,那麼你可以使用它通過添加圍繞所選擇的元素一個額外的DIV給力。

+0

正如我在原始問題中所說的,我不想編輯HTML。 – user108471

6

實際上,不可能通過純CSS來包裝另一個元素。但是我們可以通過給每個相鄰元素添加邊框並在中間邊框上放置一個絕對定位的僞元素來以某種方式來僞造效果。

另外,請注意,自定義屬性在HTML中無效,除非它們的格式爲data-*

#boxed_contents [data-boxme] { 
 
    display: inline-block; 
 
    border: 2px solid #00F; 
 
} 
 

 
#boxed_contents [data-boxme] + [data-boxme] { 
 
    margin-left: -.25em; 
 
    padding-left: .25em; 
 
    position: relative; 
 
} 
 

 
#boxed_contents [data-boxme] + [data-boxme]:after { 
 
    content: ""; 
 
    position: absolute; 
 
    top: 0; bottom: 0; left: -4px; 
 
    width: 4px; 
 
    background: white; 
 
}
<div id="boxed_contents"> 
 
    <span>hello</span> 
 
    <span>world</span> 
 
    <span data-boxme>look</span> 
 
    <span data-boxme>at</span> 
 
    <span data-boxme>me</span> 
 
    <span>not me</span> 
 
</div>

+0

如果我想堅持四捨五入的「border-radius」角,這看起來很有趣,但它是迄今爲止解決問題的唯一答案。我給這個+1,因爲它看起來不錯,只要我避免使用'border-radius'。我會接受這個答案,如果它與'border-radius'配合良好。 – user108471

+0

@ user108471恐怕不可能做到這一點,因爲CSS中沒有任何功能僅僅匹配* last * adjecent兄弟元素而不觸及中間的兄弟姐妹。 'A + A'相鄰的選擇符與從第二個'A'開始的'A'匹配。 –

+0

這個答案讓我找到了解決方案(我已發佈爲新答案)的正確軌道,該解決方案在原始問題上保留了圓角。使用兄弟選擇器和':before',我能夠完成我的目標。謝謝。 – user108471

1

this是否適合您?

var borderProps='2px solid #f00',borderRadius='5px',boxMeAttr='data-boxme'; 
var spans=document.querySelectorAll('span'),boxMeArrays=[],dummyArray=null,iterator=0; 
var currSpan=null,prevSpan=null; 
var i,length=spans.length,adjacentSpans=0; 
for(i=0; i<length; i+=1){ 
    prevSpan=currSpan; 
    currSpan=spans[i]; 
    if(currSpan.hasAttribute(boxMeAttr)){ 
     if(prevSpan!==null&&prevSpan.hasAttribute(boxMeAttr)){ 
      dummyArray[dummyArray.length]=currSpan; 
     }else{ 
      dummyArray=[currSpan]; 
      boxMeArrays[iterator]=dummyArray; 
      iterator+=1; 
     } 
    } 
} 
length=boxMeArrays.length; 
for(i=0; i<length; i+=1){ 
    adjacentSpans=boxMeArrays[i].length; 
    for(var j=0; j<adjacentSpans; j+=1){ 
     currSpan=boxMeArrays[i][j]; 
     if(adjacentSpans>1){ 
      if(j===0){ 
       currSpan.innerText+=' '; 
       currSpan.style.borderLeft=currSpan.style.borderTop=currSpan.style.borderBottom=borderProps; 
       currSpan.style.borderTopLeftRadius=currSpan.style.borderBottomLeftRadius=borderRadius; 
      }else if(j===adjacentSpans-1){ 
       currSpan.style.borderTop=currSpan.style.borderBottom=currSpan.style.borderRight=borderProps; 
       currSpan.style.borderTopRightRadius=currSpan.style.borderBottomRightRadius=borderRadius; 
      }else{ 
       currSpan.innerText+=' '; 
       currSpan.style.borderTop=currSpan.style.borderBottom=borderProps; 
      } 
     }else{ 
      currSpan.style.border=borderProps; 
      currSpan.style.borderRadius=borderRadius; 
     } 
    } 
} 

絕對不是直截了當,但我認爲它足夠好。如果你確定,只修改你的HTML:使用innerText增加一個額外的空間,所以邊界可以很好地相互連接。

看看jsFiddle上的實現。希望我沒有錯過任何細節,真正希望這個解決方案適合你。

+0

這比我所希望的複雜得多,但它完成了工作。我很欣賞你爲此付出的努力。 – user108471

+0

爲了使其具有可伸縮性,是的,它可以讓你輕鬆地在HTML中移動你的'span'元素,並且仍然可以獲得理想的效果。 –