Ревью кода. Как можна улучшить этот код?
я изучаю front-end разработку 2 .5 месяца, решил перейти на практику и написал todo list за часов 8
- Напишите, пожалуйста, свое мнение о коде и как его можно улучшить (желательно по html, css тоже, но в приоритете JS)
- Хочу начать изучение React, уже можно начинать или лучше ещё попрактиковаться на JS?
Ссылка на код: https://codepen.io/domarchuk77/pen/xxRoMBY
class Task {
constructor(){
counter++
this.taskText = document.querySelector(".todo__settings__input").value
this.task = pattern.cloneNode(true)
this.taskList = document.querySelector(".todo__list")
this.taskList.prepend(this.task)
this.taskName = document.querySelector(".todo__list__item__text")
this.itemProgress = document.querySelector(".todo__list__item")
this.taskName.innerHTML = this.taskText
this.itemProgress.classList.add("in-progress")
this.taskDelete()
this.taskComplete()
this.taskFilter()
input.value = ""
}
taskDelete(){
this.buttonDelete = document.querySelector(".todo__list__item__buttons__finish")
this.buttonDelete.addEventListener("click",() => {
this.task.remove()
counter--
console.log(counter)
if(counter == 0){
this.filter.disabled = true
this.filter.value = "all"
}
})
}
taskComplete(){
this.buttonComplete = document.querySelector(".todo__list__item__buttons__complete")
this.buttonComplete.addEventListener("click",() => {
this.buttonComplete.remove()
this.itemProgress.classList.add('task-complete')
this.filterCheckActive()
if(this.itemProgress.classList.contains('in-progress')){
this.itemProgress.classList.remove('in-progress')
}
})
}
taskFilter(){
this.filter = document.querySelector(".todo__settings__filter")
this.filter.disabled = false
this.filter.addEventListener("change",() => {
if(this.filter.value == "all"){
this.itemProgress.classList.add('show')
}else{
this.itemProgress.classList.remove('hide')
}
this.filterCheckActive()
if(this.filter.value == "complete"){
this.itemProgress.classList.remove('show')
this.itemProgress.classList.remove('hide')
if(this.itemProgress.classList.contains('in-progress')){
this.itemProgress.classList.add('hide')
}else{
this.itemProgress.classList.remove('show')
}
}
})
}
filterCheckActive(){
if(this.filter.value == "active"){
this.itemProgress.classList.remove('show')
this.itemProgress.classList.remove('hide')
if(this.itemProgress.classList.contains('task-complete')){
this.itemProgress.classList.add('hide')
}else{
this.itemProgress.classList.remove('show')
}
}
}
checkText(){
}
}
let counter = 0
let pattern = document.querySelector(".todo__list__item")
pattern.remove()
let input = document.querySelector(".todo__settings__input")
document.querySelector(".todo__settings__button").addEventListener("click", function(){
if(!(input.value.length == 0)){
new Task
}
})
/* http://meyerweb.com/eric/tools/css/reset/
v2.0-modified | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* make sure to set some focus styles for accessibility */
:focus {
outline: 0;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration,
input[type=search]::-webkit-search-results-button,
input[type=search]::-webkit-search-results-decoration {
-webkit-appearance: none;
-moz-appearance: none;
}
input[type=search] {
-webkit-appearance: none;
-moz-appearance: none;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
textarea {
overflow: auto;
vertical-align: top;
resize: vertical;
}
/**
* Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
*/
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1;
max-width: 100%;
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address styling not present in IE 7/8/9, Firefox 3, and Safari 4.
* Known issue: no IE 6 support.
*/
[hidden] {
display: none;
}
/**
* 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using
* `em` units.
* 2. Prevent iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-size: 100%; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
-ms-text-size-adjust: 100%; /* 2 */
}
/**
* Address `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: thin dotted;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/**
* 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3.
* 2. Improve image quality when scaled in IE 7.
*/
img {
border: 0; /* 1 */
-ms-interpolation-mode: bicubic; /* 2 */
}
/**
* Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
*/
figure {
margin: 0;
}
/**
* Correct margin displayed oddly in IE 6/7.
*/
form {
margin: 0;
}
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct color not being inherited in IE 6/7/8/9.
* 2. Correct text not wrapping in Firefox 3.
* 3. Correct alignment displayed oddly in IE 6/7.
*/
legend {
border: 0; /* 1 */
padding: 0;
white-space: normal; /* 2 */
*margin-left: -7px; /* 3 */
}
/**
* 1. Correct font size not being inherited in all browsers.
* 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5,
* and Chrome.
* 3. Improve appearance and consistency in all browsers.
*/
button,
input,
select,
textarea {
font-size: 100%; /* 1 */
margin: 0; /* 2 */
vertical-align: baseline; /* 3 */
*vertical-align: middle; /* 3 */
}
/**
* Address Firefox 3+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
button,
input {
line-height: normal;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+.
* Correct `select` style inheritance in Firefox 4+ and Opera.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
* 4. Remove inner spacing in IE 7 without affecting normal text inputs.
* Known issue: inner spacing remains in IE 6.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
*overflow: visible; /* 4 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* 1. Address box sizing set to content-box in IE 8/9.
* 2. Remove excess padding in IE 8/9.
* 3. Remove excess padding in IE 7.
* Known issue: excess padding remains in IE 6.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
*height: 13px; /* 3 */
*width: 13px; /* 3 */
}
/**
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof).
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/**
* Remove inner padding and search cancel button in Safari 5 and Chrome
* on OS X.
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Remove inner padding and border in Firefox 3+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* 1. Remove default vertical scrollbar in IE 6/7/8/9.
* 2. Improve readability and alignment in all browsers.
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
html,
button,
input,
select,
textarea {
color: #222;
}
::-moz-selection {
background: #b3d4fc;
text-shadow: none;
}
::selection {
background: #b3d4fc;
text-shadow: none;
}
img {
vertical-align: middle;
}
fieldset {
border: 0;
margin: 0;
padding: 0;
}
textarea {
resize: vertical;
}
.chromeframe {
margin: 0.2em 0;
background: #ccc;
color: #000;
padding: 0.2em 0;
}
@import url("./reset.css");
@import url("https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@700&display=swap");
body {
background: -webkit-gradient(linear, left top, right top, from(#b9deed), to(#efefef));
background: linear-gradient(90deg, #b9deed, #efefef);
}
* {
font-family: 'Josefin Sans', sans-serif;
outline: none;
border: solid 1px white;
}
option {
font-size: 12px;
}
.todo {
text-align: center;
width: 300px;
margin: 20px auto;
}
.todo__title {
font-family: 'Josefin Sans', sans-serif;
}
.todo__settings {
position: relative;
margin: 20px 0 0 0;
}
.todo__settings__button {
cursor: pointer;
width: 15px;
height: 15px;
position: absolute;
top: 2px;
left: 173px;
background: #268729b8;
outline: none;
border: none;
border-radius: 2px;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-transition: all 1s;
transition: all 1s;
}
.todo__settings__button:hover {
background: #29a62e;
-webkit-transition: all 1s;
transition: all 1s;
}
.todo__settings__filter {
margin: 0 0 15px 0;
}
.todo__list__item {
margin: 4px 0 0 4px;
min-width: 100%;
background: white;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
}
.todo__list__item__buttons {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.todo__list__item__buttons__button {
background: #e88931;
height: 20px;
width: 20px;
cursor: pointer;
}
.todo__list__item__buttons__complete {
background: #268729b8;
}
.todo__list__item__buttons__text {
padding: 5px;
}
.line {
background: white;
position: absolute;
width: 6px;
height: 2px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.line2 {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.task-complete {
text-decoration: line-through;
color: #063607;
}
.hide {
display: none;
}
.show {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
/*# sourceMappingURL=style.css.map */
<div class="todo">
<div class="todo__title">Ed's Todo List </div>
<div class="todo__settings">
<input type="text" class="todo__settings__input" />
<div class="todo__settings__button">
<div class="line1 line"></div>
<div class="line2 line"></div>
</div>
<select class="todo__settings__filter" disabled>
<option value="all">All</option>
<option value="active">Active</option>
<option value="complete">Complete</option>
</select>
</div>
<div class="todo__list">
<div class="todo__list__item">
<div class="todo__list__item__text"></div>
<div class="todo__list__item__buttons">
<div class="todo__list__item__buttons__complete todo__list__item__buttons__button" >
<img width="13px" src="https://img.icons8.com/android/50/000000/checkmark.png"/>
</div>
<div class="todo__list__item__buttons__button todo__list__item__buttons__finish">
<img width="13px" src="https://img.icons8.com/wired/50/000000/empty-trash.png"/>
</div>
</div>
</div>
</div>
</div>
Ответы (1 шт):
constructor(){ counter++ — обращение к внешней переменной, объявление которой потерялось где-то ниже класса. Если счетчик относится непосредственно к классу, почему бы не сделать его свойством этого класса? И в дальнейшем обращаться к нему в виде Task.counter++; А если по какой-то причине действительно необходима внешняя переменная, приятнее было бы видеть её объявление еще до класса, чтобы при чтении сразу понять, с чем имеем дело (название ведь может быть менее очевидным, чем просто counter - его придется искать в коде);
this...
this...
< 2000 years later... >
this...
this...
Хорошо бы как-то визуально разделять код на логические блоки, добавляя пробельные строчки) Даже в случае обычного текста: Монолитный блок букв воспринимается труднее, чем мысли, разбитые по абзацам.
Названия методов taskDelete(), taskComplete(), taskFilter(): Весь класс — это и есть task, поэтому эти приставки можно опустить. Обращение task.delete() будет вполне естественной, вместо task.taskDelete()
UPD: Как оказывается, они в свою очередь, выполняют не совсем то, о чем говорят их названия. Добавляют обработчики кликов на конкретные кнопки.
Вообще говоря, объявленные в классе методы() создаются один раз, в момент создания класса, и доступны для использования у всех объектов, созданных классом (экземпляров). А ваши методы для каждой «задачи» создают новые функции для обработки кликов. В контексте такой программы не серьезно говорить про экономию памяти (+/-1КБ?), но в целом, полезно об этом помнить.
this.buttonComplete.remove() — удаляется HTML-объект из DOM, но ссылка на него остается в this.buttonComplete, из-за чего объект продолжает храниться в памяти. Это тоже полезно держать в уме. Лечится выполнением delete this.buttonComplete.
class="todo__list__item__buttons__complete todo__list__item__buttons__button" — Идея понятна, но с такими классами может быть больно работать в дальнейшем. Будет полезно ознакомиться с похожим стилем именований классов BEM (Block, Element, Modifier).
Постоянным переключением классов show / hide создали себе лишнюю работу. Достаточно всем элементам по умолчанию выдать стили show, а если нужно скрыть элемент - включить у него класс hide;
this.taskText = document.querySelector(".todo__settings__input").value — Классу, который создает «Задачу», совсем не объязательно знать, откуда он должен брать данные. Мог бы получить текст и выдать готовый HTML-узел задачи.
Тут не может быть единственно верного решения, т.к. изначально ООП — способ организации большого кода. А попытки протолкнуть его в программы, состоящие из трех функций, всегда выглядят искусственно (вообще, «todo» хорошо подходит для изучения делегирования событий). Всё же, кое-как можно пробовать.
* HTML не трогал, функционал тоже не менял, работает как у вас, немного другим кодом.
const doc = {
// Мини-библиотека :) Чтобы много не писать document.querySelector
first: function (selector, root) {
return (root || document).querySelector(selector);
},
};
/***/
class Filter {
// Класс одноразовый.
// Это попытка вынести логику фильтрации из Task
// Можно было бы прописать в виде Task.filter = new (class { ... })();
constructor() {
let root = this.root = doc.first(".todo__settings__filter");
root.addEventListener("change", () => this.update());
}
update() {
if (Task.count == 0) {
this.root.disabled = true;
this.root.value = "all";
return;
}
this.root.disabled = false;
let filterType = this.root.value;
let list = Task.getList(filterType);
Task.showOnly(list);
}
}
class Task {
static count = 0;
static list = [];
static filter = new Filter();
constructor(text) {
let root = this.root = this._createTaskNode(text);
this.btn = {
complete: doc.first(".todo__list__item__buttons__complete", root),
};
/***/
this._initEventListeners(root);
Task.list.push(this);
Task.count++;
/***/
this.isComplete = false; // Состояние указывается явно в виде свойства
// и больше не привязано к наличию класса в HTML
Task.filter.update();
}
_createTaskNode(text) {
let div = document.createElement('div');
div.innerHTML = (`
<div class="todo__list__item in-progress">
<div class="todo__list__item__text">${ text }</div>
<div class="todo__list__item__buttons">
<div class="todo__list__item__buttons__button todo__list__item__buttons__complete">
<img width="13px" src="https://img.icons8.com/android/50/000000/checkmark.png"/>
</div>
<div class="todo__list__item__buttons__button todo__list__item__buttons__finish">
<img width="13px" src="https://img.icons8.com/wired/50/000000/empty-trash.png"/>
</div>
</div>
</div>
`);
return div.firstElementChild;
}
_initEventListeners(root) {
let del = doc.first(".todo__list__item__buttons__finish", root);
del.addEventListener("click", () => this.delete());
this.btn.complete.addEventListener("click", () => this.complete());
}
delete() {
this.root.remove();
Task.count--;
let index = Task.list.indexOf(this);
Task.list.splice(index, 1);
Task.filter.update();
}
complete() {
this.btn.complete.remove();
delete this.btn.complete;
this.root.classList.remove("in-progress");
this.root.classList.add("task-complete");
this.isComplete = true;
Task.filter.update();
}
show() {
this.root.classList.remove("hide");
}
hide() {
this.root.classList.add("hide");
}
/***/
static getList(type) {
type = type.trim().toLowerCase();
switch (type) {
case "all": return Task.list;
case "active": return Task.list.filter(e => !e.isComplete);
case "complete": return Task.list.filter(e => e.isComplete);
default: throw new Error("Expected: { all | active | complete }, but found: " + type);
}
}
static showOnly(list) {
Task.list.forEach(e => e.hide());
list.forEach(e => e.show());
}
}
/***/
let input = doc.first(".todo__settings__input");
let todo = doc.first(".todo__list");
doc.first(".todo__settings__button").addEventListener("click", function () {
if (!input.value) return;
let task = new Task(input.value);
todo.appendChild(task.root); // вставка в HTML специально вынесена из класса.
// Класс: Создал - выдал. Не важно кому и куда.
});
/* http://meyerweb.com/eric/tools/css/reset/
v2.0-modified | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* make sure to set some focus styles for accessibility */
:focus {
outline: 0;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration,
input[type=search]::-webkit-search-results-button,
input[type=search]::-webkit-search-results-decoration {
-webkit-appearance: none;
-moz-appearance: none;
}
input[type=search] {
-webkit-appearance: none;
-moz-appearance: none;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
textarea {
overflow: auto;
vertical-align: top;
resize: vertical;
}
/**
* Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
*/
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1;
max-width: 100%;
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address styling not present in IE 7/8/9, Firefox 3, and Safari 4.
* Known issue: no IE 6 support.
*/
[hidden] {
display: none;
}
/**
* 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using
* `em` units.
* 2. Prevent iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-size: 100%; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
-ms-text-size-adjust: 100%; /* 2 */
}
/**
* Address `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: thin dotted;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/**
* 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3.
* 2. Improve image quality when scaled in IE 7.
*/
img {
border: 0; /* 1 */
-ms-interpolation-mode: bicubic; /* 2 */
}
/**
* Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
*/
figure {
margin: 0;
}
/**
* Correct margin displayed oddly in IE 6/7.
*/
form {
margin: 0;
}
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct color not being inherited in IE 6/7/8/9.
* 2. Correct text not wrapping in Firefox 3.
* 3. Correct alignment displayed oddly in IE 6/7.
*/
legend {
border: 0; /* 1 */
padding: 0;
white-space: normal; /* 2 */
*margin-left: -7px; /* 3 */
}
/**
* 1. Correct font size not being inherited in all browsers.
* 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5,
* and Chrome.
* 3. Improve appearance and consistency in all browsers.
*/
button,
input,
select,
textarea {
font-size: 100%; /* 1 */
margin: 0; /* 2 */
vertical-align: baseline; /* 3 */
*vertical-align: middle; /* 3 */
}
/**
* Address Firefox 3+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
button,
input {
line-height: normal;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+.
* Correct `select` style inheritance in Firefox 4+ and Opera.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
* 4. Remove inner spacing in IE 7 without affecting normal text inputs.
* Known issue: inner spacing remains in IE 6.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
*overflow: visible; /* 4 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* 1. Address box sizing set to content-box in IE 8/9.
* 2. Remove excess padding in IE 8/9.
* 3. Remove excess padding in IE 7.
* Known issue: excess padding remains in IE 6.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
*height: 13px; /* 3 */
*width: 13px; /* 3 */
}
/**
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof).
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/**
* Remove inner padding and search cancel button in Safari 5 and Chrome
* on OS X.
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Remove inner padding and border in Firefox 3+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* 1. Remove default vertical scrollbar in IE 6/7/8/9.
* 2. Improve readability and alignment in all browsers.
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
html,
button,
input,
select,
textarea {
color: #222;
}
::-moz-selection {
background: #b3d4fc;
text-shadow: none;
}
::selection {
background: #b3d4fc;
text-shadow: none;
}
img {
vertical-align: middle;
}
fieldset {
border: 0;
margin: 0;
padding: 0;
}
textarea {
resize: vertical;
}
.chromeframe {
margin: 0.2em 0;
background: #ccc;
color: #000;
padding: 0.2em 0;
}
@import url("./reset.css");
@import url("https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@700&display=swap");
body {
background: -webkit-gradient(linear, left top, right top, from(#b9deed), to(#efefef));
background: linear-gradient(90deg, #b9deed, #efefef);
}
* {
font-family: 'Josefin Sans', sans-serif;
outline: none;
border: solid 1px white;
}
option {
font-size: 12px;
}
.todo {
text-align: center;
width: 300px;
margin: 20px auto;
}
.todo__title {
font-family: 'Josefin Sans', sans-serif;
}
.todo__settings {
position: relative;
margin: 20px 0 0 0;
}
.todo__settings__button {
cursor: pointer;
width: 15px;
height: 15px;
position: absolute;
top: 2px;
left: 173px;
background: #268729b8;
outline: none;
border: none;
border-radius: 2px;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-transition: all 1s;
transition: all 1s;
}
.todo__settings__button:hover {
background: #29a62e;
-webkit-transition: all 1s;
transition: all 1s;
}
.todo__settings__filter {
margin: 0 0 15px 0;
}
.todo__list__item {
margin: 4px 0 0 4px;
min-width: 100%;
background: white;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
}
.todo__list__item__buttons {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.todo__list__item__buttons__button {
background: #e88931;
height: 20px;
width: 20px;
cursor: pointer;
}
.todo__list__item__buttons__complete {
background: #268729b8;
}
.todo__list__item__buttons__text {
padding: 5px;
}
.line {
background: white;
position: absolute;
width: 6px;
height: 2px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.line2 {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.task-complete {
text-decoration: line-through;
color: #063607;
}
.hide {
display: none;
}
/*# sourceMappingURL=style.css.map */
<div class="todo">
<div class="todo__title">Ed's Todo List </div>
<div class="todo__settings">
<input type="text" class="todo__settings__input" />
<div class="todo__settings__button">
<div class="line1 line"></div>
<div class="line2 line"></div>
</div>
<select class="todo__settings__filter" disabled>
<option value="all">All</option>
<option value="active">Active</option>
<option value="complete">Complete</option>
</select>
</div>
<div class="todo__list"></div>
</div>