CSS 클래스가 하나 이상의 다른 클래스를 상속 할 수 있습니까?


735

나는 오랫동안 웹 프로그래머가 되어서이 질문에 대한 답을 알지 못하는 것에 대해 바보 같은 느낌을 느낍니다. 실제로 그것이 가능하기를 희망하며 대답이라고 생각하는 것보다는 (아직 불가능합니다) 몰랐습니다. .

내 질문은 다른 CSS 클래스 (또는 둘 이상)에서 "상속"하는 CSS 클래스를 만들 수 있는지 여부입니다.

예를 들어 다음과 같이 가정 해 봅시다.

.something { display:inline }
.else      { background:red }

내가하고 싶은 것은 다음과 같습니다.

.composite 
{
   .something;
   .else
}

".composite"클래스는 인라인으로 표시되고 배경은 빨간색입니다.


3
상속보다는 계단식에 대해 더 많이 생각하면 여기에 적용되지 않습니다.
blu

답변:


427

LESS 와 같은 도구가 있습니다.이 도구 를 사용하면 설명과 유사한 추상화 수준으로 CSS를 작성할 수 있습니다.

이 "Mixins"라고 부르는 사람

대신에

/* CSS */
#header {
  -moz-border-radius: 8px;
  -webkit-border-radius: 8px;
  border-radius: 8px;
}

#footer {
  -moz-border-radius: 8px;
  -webkit-border-radius: 8px;
  border-radius: 8px;
}

넌 말할 수있다

/* LESS */
.rounded_corners {
  -moz-border-radius: 8px;
  -webkit-border-radius: 8px;
  border-radius: 8px;
}

#header {
  .rounded_corners;
}

#footer {
  .rounded_corners;
}

37
와우, LESS는 내가 찾고있는 것과 거의 똑같습니다. 그것은 기본적으로 지원되지 않으며, 루비로 작성되었다는 수치입니다 (ASP.NET MVC를 사용하고 있습니다)
Joel Martinez

1
예, ASP.NET 환경에서도 프로덕션 워크 플로로 옮기지 않았습니다.
Larsenal 2016 년

덜 아름답고 유혹적입니다 ...하지만 동일한 워크 플로우에서 CSSEdit을 사용하여 성공적으로 사용하지 못 했으므로 아직 완전히 채택하지 못했습니다.
Ryan Florence

1
그래 LESS는 꽤 달콤하지 않습니까. 필자는 실제로 .NET 포트에서 작업했습니다 : nlesscss.codeplex.com .
Owen

77
경우에 당신이 구글을 통해이 도달 : 닷넷 포트는 지금 여기에
Eonasdan

309

단일 DOM 요소에 여러 클래스를 추가 할 수 있습니다 (예 :

<div class="firstClass secondClass thirdclass fourthclass"></div>

이후 클래스에서 제공되는 규칙 (또는보다 구체적인 규칙)이 재정의됩니다. 따라서이 fourthclass예에서는 우선합니다.

상속은 CSS 표준의 일부가 아닙니다.


12
어떤 클래스가 우선하는지, 마지막 클래스 또는 첫 번째 클래스인지, 브라우저 간 동작이 안전한지 알고 있습니까? 우리가 .firstClass {font-size:12px;} .secondClass {font-size:20px;}최종적 font-size으로 12px또는 20px이 크로스 브라우저를 안전하게 사용할 수 있다고 가정 해 봅시다 .
Marco Demaio

27
선택기에서 가장 높은 특이성을 가진 규칙이 승리합니다. 표준 특이성 규칙이 적용됩니다. 예를 들어, "first"와 "second"는 같은 특성을 가지므로 나중에 CSS에서 선언 된 규칙이 우선합니다.
Matt Bridges

19
이 문제를 해결하기 위해 LESS 대신 순수 CSS를 사용하는 아이디어가 마음에 듭니다.
Alex

8
나는 또한 여러 클래스를 여러 번 입력하지 않는 아이디어를 좋아합니다-O (n ^ 2) 작업입니다 :)
Secret

3
타사 lib를 사용하고 있으며 제공하는 디자인 / HTML을 수정하려고하지만 해당 lib의 내장 CSS 파일을 변경할 수없는 경우 어떻게해야합니까? 거기에 CSS 클래스에서 일종의 상속이 필요합니다.
Shivam 's

112

예, 그러나 해당 구문과 정확히 일치하지는 않습니다.

.composite,
.something { display:inline }

.composite,
.else      { background:red }

7
이 짜증, 그러나 나는 우리가 적어도 이것을 가지고 기쁘다!
Pacerier

3
왜 짜증나? 아주 좋아 보인다. 쉼표 기호와 less.js 솔루션의 차이점을 이해할 수 없습니다.
Revious

21
.something 클래스와 .else 클래스가 다른 파일에 있고 수정할 수없는 경우에는 문제가 발생하기 때문입니다.
Alexandre Mélard

8
순수한 CSS 구문을 사용하여 질문에 대답했기 때문에 정답이었습니다. 적은 대답은 알면 좋습니다.
raddevus

1
이것은 예외 답변이어야합니다.
eaglei22

66

공통 속성을 함께 유지하고 특정 (또는 대체) 속성을 다시 지정하십시오.

/*  ------------------------------------------------------------------------------ */   
/*  Headings */ 
/*  ------------------------------------------------------------------------------ */   
h1, h2, h3, h4
{
    font-family         : myfind-bold;
    color               : #4C4C4C;
    display:inline-block;
    width:900px;
    text-align:left;
    background-image: linear-gradient(0,   #F4F4F4, #FEFEFE);/* IE6 & IE7 */
}

h1  
{
    font-size           : 300%;
    padding             : 45px 40px 45px 0px;
}

h2
{
    font-size           : 200%;
    padding             : 30px 25px 30px 0px;
}

2
이것은 이상적인 솔루션에 매우 가깝습니다. 투표가 거의 없기 때문에 사람들이 그것을 버리지 않기를 바랍니다. 실제로 "CSS 상속"에 대한 가장 어려운 문제 중 하나는 일반적으로 이미 제작 된 거대한 웹 소프트웨어 (예 : 전자 상거래 또는 블로그 PHP 유명 소프트웨어)를 얻고 기본적으로 PHP 코드를 사용한다는 것입니다. t HTML 요소에 여러 클래스를 추가하지 마십시오. 이렇게하면 소스 코드 (나중에 업그레이드하면 변경 사항이 없어짐)로 이동하여 추가 클래스를 출력하게됩니다. 이 방법을 사용하면 CSS 파일 만 편집 할 수 있습니다.
Dario Fumagalli

3
이것은 내가 찾던 것입니다. 이 같은 접근 방식이 CSS 선택기와 함께 작동하는 것이 가치가 있습니까? 지정하는 대신 다음을 지정할 h1, h2, etc수 있습니다..selector1, .selector2, .etc
JeffryHouser

이것이 권장 된 기본 html 스타일 시트에서 [w3 CSS2] : w3.org/TR/CSS2/sample.html 에서 w3에 의해 사용 된 접근법이라고 언급하고 싶었 습니다 . CSS 코드를 구성하는 방법을 파악하려고 노력하고 있으며 일반적인 객체 지향 상속과 비교하여 패러다임이 반전 된 것처럼 보입니다. 클래스 (또는 일반적으로 선택기)를 사용하여 어떤 요소가 어떤 속성을 상속하는지 지정하고, 그러나 속성상속받습니다 (적어도 계층 구조가 논리적으로 가장 쉽게 존재하는 방법 임). 필요한 경우보다 구체적인 선택기에서 속성을 재정의합니다.
Nathan Chappell

50

요소는 여러 클래스를 사용할 수 있습니다.

.classOne { font-weight: bold; }
.classTwo { font-famiy:  verdana; }

<div class="classOne classTwo">
  <p>I'm bold and verdana.</p>
</div>

그리고 그것은 불행히도 거의 다가올 것입니다. 언젠가 클래스 별명과 함께이 기능을보고 싶습니다.


44

아니요 당신은 같은 것을 할 수 없습니다

.composite 
{
   .something;
   .else
}

이것은 OO 의미에서 "클래스"이름이 아닙니다. .something그리고 .else아무것도 더 단지 선택기입니다.

그러나 요소에 두 개의 클래스를 지정할 수 있습니다

<div class="something else">...</div>

아니면 다른 형태의 상속을 살펴볼 수도 있습니다

.foo {
  background-color: white;
  color: black;
}

.bar {
  background-color: inherit;
  color: inherit;
  font-weight: normal;
}
<div class="foo">
  <p class="bar">Hello, world</p>
</div>

단락의 배경색과 색은 .foo스타일 이 지정된 둘러싸는 div의 설정에서 상속됩니다 . 정확한 W3C 사양을 확인해야 할 수도 있습니다. inherit어쨌든 대부분의 속성에는 기본값이지만 전부는 아닙니다.


1
예, 이것은 20 세기에 CSS를 처음 들었을 때의 나의 기대였습니다 ... 그리고 우리는 여전히 그것을 가지고 있지 않습니다. 변수의 필요성을 대체합니다 (정적 "변수")
neu-rah

30

나는이 같은 문제에 부딪 쳤고 JQuery 솔루션을 사용하여 클래스가 다른 클래스를 상속받을 수있는 것처럼 보이게되었습니다.

<script>
    $(function(){
            $(".composite").addClass("something else");
        });
</script>

"composite"클래스를 가진 모든 요소를 ​​찾고 "something"및 "else"클래스를 요소에 추가합니다. 따라서 다음과 같이 <div class="composite">...</div>끝납니다.
<div class="composite something else">...</div>


1
이 솔루션의 문제점은 기존의 모든 컨트롤에 적용된다는 것입니다.이 호출 후에 컨트롤을 만들면 새 클래스가 없습니다.
LuisEduardoSP

27

주어진 예제 의 SCSS 방식은 다음과 같습니다.

.something {
  display: inline
}
.else {
  background: red
}

.composite {
  @extend .something;
  @extend .else;
}

더 많은 정보, sass 기본 사항 확인


이에 비해 부가가치는 무엇입니까? .composite,.something { display:inline }.composite,.else { background:red }
파벨 Gatnar

2
@PavelGatnar 다른 CSS 정의 .something.else다른 CSS 정의를 재사용 할 수 있습니다.
Alter Lagos

15

당신이 할 수있는 최선은 이것입니다

CSS

.car {
  font-weight: bold;
}
.benz {
  background-color: blue;
}
.toyota {
  background-color: white;
}

HTML

<div class="car benz">
  <p>I'm bold and blue.</p>
</div>
<div class="car toyota">
  <p>I'm bold and white.</p>
</div>

12

잊지 마세요 :

div.something.else {

    // will only style a div with both, not just one or the other

}

1
메신저는 찾고 있지,하지만이 n__n 나를 위해 건설했다
AgelessEssence

7

Css 파일에서 :

p.Title 
{
  font-family: Arial;
  font-size: 16px;
}

p.SubTitle p.Title
{
   font-size: 12px;
}

2
결과는 font-size무엇입니까?
abatishchev

"p.Title"의 글꼴 크기는 파일의 첫 번째 글꼴 뒤에 정의되므로 12px입니다. 첫 번째 글꼴 크기보다 우선합니다.
YWE

@YWE : 이것은 선언이 실제로이 답변에 쓰여진 것과 비교하여 다른 방향이어야한다는 것을 의미합니까? 마지막으로 정의 된 것이 우선하는 경우, 적용 font-size: 16px할 수 없습니다.
또는 매퍼

@ORMapper-일반적으로 첫 번째 선언은 공통 CSS 파일에 있으며 여러 페이지에서 공유됩니다. 그런 다음 두 번째 선언은 두 번째 CSS 파일에 있으며 특정 페이지에서만 사용됩니다. 그리고 일반적인 CSS 파일 이후 에 가져 옵니다. 따라서 해당 페이지는 "마지막"값을 사용 12px합니다.
ToolmakerSteve

7

나는이 질문이 지금 매우 오래되었다는 것을 알고 있지만 여기서는 아무것도 아닙니다!

기본 솔루션으로 여러 클래스의 속성을 암시하는 단일 클래스를 추가하려는 경우 JavaScript / jQuery를 사용하는 것이 좋습니다 (jQuery는 실제로 필요하지 않지만 확실히 유용합니다)

예를 들어 .umbrellaClass"상속"이 .baseClass1있고 .baseClass2준비된 JavaScript가있을 수 있습니다.

$(".umbrellaClass").addClass("baseClass1");
$(".umbrellaClass").addClass("baseClass2");

이제의 모든 요소 .umbrellaClass는 두 .baseClass의 모든 속성을 갖습니다 . OOP 상속과 마찬가지로 .umbrellaClass자체 속성이 있거나 없을 수 있습니다.

여기서 유일한 경고는이 코드가 실행될 때 존재하지 않는 동적으로 생성되는 요소가 있는지 여부를 고려하는 것입니다. 그러나 그 주위에 간단한 방법도 있습니다.

그러나 css는 네이티브 상속이 없습니다.


1
이 접근 방식은 2013 년 @DHoover의 답변 에서 이미 제안되었습니다 .
Bryan

6

완벽한 타이밍 : 나는이 질문에서 내 이메일로 갔으며 , Ruby 라이브러리 인 Less 에 관한 기사를 찾기 위해 무엇 보다도이 작업을 수행했습니다.

super 모양은 같지만 글꼴이 다르기 때문에 footerLess의 클래스 포함 기술 (믹스 인이라고 함)을 사용하여 이러한 선언도 포함하도록 지시합니다.

#super {
  #footer;
  font-family: cursive;
}

LESS가 더 이상 나를 놀라게 할 수 없다고 생각했을 때 ...이 같은 다른 블록에서 형식을 가져올 수 있을지 몰랐습니다. 좋은 팁.
Daniel Rippstein

4

불행히도 CSS는 C ++, C # 또는 Java와 같은 프로그래밍 언어가하는 방식으로 '상속'을 제공하지 않습니다. CSS 클래스를 선언 한 다음 다른 CSS 클래스로 확장 할 수 없습니다.

그러나 마크 업의 태그에 하나 이상의 클래스를 적용 할 수 있습니다.이 경우 브라우저에서 적용 할 실제 스타일을 결정하는 복잡한 규칙이 있습니다.

<span class="styleA styleB"> ... </span>

CSS는 마크 업에 따라 적용 할 수있는 모든 스타일을 찾고 여러 규칙의 CSS 스타일을 결합합니다.

일반적으로 스타일은 병합되지만 충돌이 발생하면 나중에 선언 된 스타일이 일반적으로 이깁니다 (! important 속성이 스타일 중 하나에 지정되지 않은 경우이기는 경우). 또한 HTML 요소에 직접 적용된 스타일은 CSS 클래스 스타일보다 우선합니다.


귀하의 답변은 Google에서 첫 번째 결과로 나타 났으며 도움이되었습니다. 즉, 팁이 있습니다-솔루션을 제공하는 경우 문장을 부정적으로 시작하지 않는 것이 가장 좋습니다 (불행히도 CSS는 상속을 제공하지 않습니다.) 나는 적절한 인내심을 가진 사람이 당신의 멋진 솔루션을 찾기 위해 읽을 것이라고 알고 있습니다. 그러나 때때로 사람들은 인내심이 부족하여 그들이하려는 일이 불가능하다는 결론에 돌입 할 수 있습니다. 다른 사람을 도울 수있는 가장 좋은 기회를 얻으려면 "CSS에는 상속이 없지만 필요한 것을 달성 할 수 있습니다 ..."와 같이 시작할 수 있습니다.
egmfrs

4

SASS도 있으며 http://sass-lang.com/ 에서 찾을 수 있습니다 . @extend 태그와 믹스 인 타입 시스템이 있습니다. (루비)

LESS의 경쟁자입니다.


4

CSS에서는 불가능합니다.

CSS에서 지원되는 유일한 것은 다른 규칙보다 더 구체적입니다.

span { display:inline }
span.myclass { background: red }

"myclass"클래스가있는 범위에는 두 속성이 모두 있습니다.

다른 방법은 두 개의 클래스를 지정하는 것입니다.

<div class="something else">...</div>

"else"스타일은 "something"스타일을 재정의 (또는 추가)합니다.


1 파일의 모든 스타일에 대해 CSS에는 상속과 같은 솔루션이 있습니다. 내 게시물을 참조하십시오.
Pavel Gatnar

3

이 class = "something else"와 같은 방법으로 하나 이상의 CSS 클래스를 요소에 적용 할 수 있습니다.


3

다른 사람들이 말했듯이 요소에 여러 클래스를 추가 할 수 있습니다.

그러나 그것은 실제로 요점이 아닙니다. 상속에 대한 질문이 있습니다. 진짜 점은 CSS의 상속이 이루어집니다한다는 것입니다 하지 수업을 통해,하지만 요소 계층 구조를 통해. 따라서 상속 된 특성을 모델링하려면 DOM의 다른 수준의 요소에 적용해야합니다.


모든 작성 클래스 체인을 사용하는 대신 상속과 같은 CSS 정의를 작성하는 것이 좋습니다. 내 게시물을 참조하십시오.
Pavel Gatnar

2

나도 그 미친 짓을 찾고 있었고 다른 것들을 시도하여 알아 냈습니다.

composite.something, composite.else
{
    blblalba
}

그것은 갑자기 나를 위해 일했다 :)


2

특정 상황에서는 "소프트"상속을 수행 할 수 있습니다.

.composite
{
display:inherit;
background:inherit;
}

.something { display:inline }
.else      { background:red }

자식 요소에 .composite 클래스를 추가하는 경우에만 작동합니다. .composite에 지정되지 않은 값은 명백하게 상속되지 않기 때문에 "소프트"상속입니다. 단순히 "상속"대신 "인라인"과 "빨간색"을 쓰는 것은 문자 수가 적을 것임을 명심하십시오.

다음은 속성 목록과이를 자동으로 수행하는지 여부입니다. https://www.w3.org/TR/CSS21/propidx.html


2

직접적인 상속은 불가능하지만

부모 태그에 클래스 (또는 id)를 사용한 다음 CSS 결합기를 사용하여 자식 태그 동작을 계층 구조에서 변경할 수 있습니다.

p.test{background-color:rgba(55,55,55,0.1);}
p.test > span{background-color:rgba(55,55,55,0.1);}
p.test > span > span{background-color:rgba(55,55,55,0.1);}
p.test > span > span > span{background-color:rgba(55,55,55,0.1);}
p.test > span > span > span > span{background-color:rgba(55,55,55,0.1);}
p.test > span > span > span > span > span{background-color:rgba(55,55,55,0.1);}
p.test > span > span > span > span > span > span{background-color:rgba(55,55,55,0.1);}
p.test > span > span > span > span > span > span > span{background-color:rgba(55,55,55,0.1);}
p.test > span > span > span > span > span > span > span > span{background-color:rgba(55,55,55,0.1);}
<p class="test"><span>One <span>possible <span>solution <span>is <span>using <span>multiple <span>nested <span>tags</span></span></span></span></span></span></span></span></p>

예제와 같이 많은 범위를 사용하는 것은 좋지 않지만 개념 증명 일뿐입니다. 이러한 방식으로 CSS를 적용하려고 할 때 발생할 수있는 많은 버그가 여전히 있습니다. (예 : 텍스트 장식 유형 변경).


2

Less and Sass는 CSS 언어를 유용한 방식으로 확장하는 CSS 전 처리기입니다. 그들이 제공하는 많은 개선 사항 중 하나는 당신이 찾고있는 옵션입니다. Less에는 아주 좋은 답변이 있으며 Sass 솔루션을 추가 할 것입니다.

Sass에는 한 클래스를 다른 클래스로 완전히 확장 할 수있는 확장 옵션이 있습니다. 이 기사에서 읽을 수있는 확장에 대한 자세한 내용



1

CSS는 실제로 원하는 것을 하지 않습니다 . 복합적인 아이디어를 염두에두고 규칙을 작성하려면 compass 를 확인하십시오 . 이미 언급 한 Less와 유사한 스타일 시트 프레임 워크입니다.

믹스 인과 모든 훌륭한 사업을 할 수 있습니다.


위에 Compass aka Sass에 더 자세한 내용을 추가하면 확장, PlaceHolders Mixins vs Extend , PlaceHolders
Abhijeet

1

언급 된 (우수한) 게시물에 만족하지 않는 사람들을 위해 프로그래밍 기술을 사용하여 변수 (PHP 또는 둘 중 하나)를 만들고 여러 클래스 이름을 저장할 수 있습니다.

그것은 내가 생각해 낼 수있는 최고의 해킹입니다.

<style>
.red { color: red; }
.bold { font-weight: bold; }
</style>

<? define('DANGERTEXT','red bold'); ?>

그런 다음 클래스 이름 자체가 아닌 원하는 요소에 전역 변수를 적용하십시오.

<span class="<?=DANGERTEXT?>"> Le Champion est Ici </span>


1

CSS 클래스 를 객체 지향 클래스 로 생각하지 말고 html 요소의 스타일 을 지정하는 속성 클래스 를 지정하는 다른 선택기 중 하나의 도구로 생각하십시오 . 중괄호 사이의 모든 것을 속성 클래스 로 생각 하고 왼쪽의 선택기 는 속성 클래스 에서 속성 을 상속 하기 위해 선택한 요소를 알려줍니다 . 예:

.foo, .bar { font-weight : bold; font-size : 2em; /* attribute class A */}
.foo { color : green; /* attribute class B */}

요소에 속성이 주어지면, class="foo"클래스 .foo에서 속성을 상속하는 것이 아니라 속성 클래스 A속성 클래스 B 에서 속성 을 생각하는 것이 유용합니다 . 즉, 상속 그래프는 속성 클래스 에서 파생되는 요소 와 가장자리가 이동하는 위치를 지정하고 선택 속성이 경쟁 속성이있을 때 우선 순위를 결정하는 방법 (방법 해결 순서와 유사 함)을 갖는 한 수준의 깊이 입니다.

여기에 이미지 설명을 입력하십시오

프로그래밍에 대한 실질적인 의미는 이것입니다. 당신이 위의 스타일 시트를 말해봐, 새로운 클래스를 추가 할 수 .baz는 동일해야한다, font-size등을 .foo. 순진한 해결책은 다음과 같습니다.

.foo, .bar { font-weight : bold; font-size : 2em; /* attribute class A */}
.foo { color : green; /* attribute class B */}
.baz { font-size : 2em; /* attribute class C, hidden dependency! */}

여기에 이미지 설명을 입력하십시오

무언가를 두 번 입력해야 할 때마다 너무 화가납니다! 뿐만 아니라 나는 두 번을 작성해야합니까, 지금은 프로그래밍 방식을 나타내는 방법이 없습니다 .foo.baz동일해야 font-size하고, 내가 만든 숨겨진 의존성을! 위의 패러다임은 속성 클래스 Afont-size 에서 속성을 추출해야한다고 제안합니다 .

.foo, .bar, .baz { font-size : 2em; /* attribute base class for A */}
.foo, .bar { font-weight : bold; /* attribute class A */}
.foo { color : green; /* attribute class B */}

여기에 이미지 설명을 입력하십시오

여기서 주요 불만은 이제 속성 클래스 A 에서 모든 선택자를 다시 입력 하여 선택 해야하는 요소가 속성 기본 클래스 A의 속성을 상속하도록 지정해야한다는 것 입니다. 여전히 대안은 무언가가 변경 될 때마다 숨겨진 종속성이있는 모든 속성 클래스 를 편집 하거나 타사 도구를 사용해야 한다는 것을 기억해야합니다 . 첫 번째 옵션은 신을 웃게 만들고, 두 번째 옵션은 나를 죽이고 싶어합니다.


0

LESS보다 강력한 텍스트 전처리기를 원하면 PPWizard를 확인하십시오.

http://dennisbareis.com/ppwizard.htm

웹 사이트는 참으로 끔찍하고 학습 곡선이 적지 만 매크로를 통해 CSS와 HTML 코드를 작성하는 데 완벽합니다. 더 많은 웹 코더가 왜 그것을 사용하지 않는지 이해하지 못했습니다.


11
웹 사이트 정말 끔찍합니다.
nanofarad

웹 사이트에서 html 프로세서를위한 아이러니 한 종류!
Ben Thurley

2
예, 웹 사이트는 끔찍하지만 그 이상입니다. 읽기 어렵고 머리도 아프다!
ArtOfWarfare

1
좋은 일이 윈도우와 호환 있다는 XP, 롤 3.1
알터 라고스

기괴한 비표준 도구입니다.
berkus

-6

PHP를 통해 .css 파일을 사전 처리하면 원하는 것을 얻을 수 있습니다. ...

$something='color:red;'
$else='display:inline;';
echo '.something {'. $something .'}';
echo '.else {'. $something .'}';
echo '.somethingelse {'. $something  .$else '}';

...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.