Flutter Simple and Robust DropdownSearch with Item Search Feature

Flutter DropdownSearch 
Flutter simple and robust DropdownSearch with item search feature, making it possible to use an offline item list or filtering URL for easy customization.

Key FeaturesExamplesLicense

Dropdown search

Key Features

  • Sync and/or Async items (online, offline, DB, ...)
  • Searchable dropdown
  • Three dropdown mode: Menu/ BottomSheet/ Dialog
  • Single & multi selection
  • Material dropdown
  • Easy customizable UI
  • Handle Light and Dark theme
  • Easy implementation into statelessWidget

packages.yaml

dropdown_search: <lastest version>

Import

import 'package:dropdown_search/dropdown_search.dart';

Simple implementation

DropdownSearch<String>(
    mode: Mode.MENU,
    showSelectedItem: true,
    items: ["Brazil", "Italia (Disabled)", "Tunisia", 'Canada'],
    label: "Menu mode",
    hint: "country in menu mode",
    popupItemDisabled: (String s) => s.startsWith('I'),
    onChanged: print,
    selectedItem: "Brazil"),
    
    
DropdownSearch<String>.multiSelection(
    mode: Mode.MENU,
    showSelectedItem: true,
    items: ["Brazil", "Italia (Disabled)", "Tunisia", 'Canada'],
    label: "Menu mode",
    hint: "country in menu mode",
    popupItemDisabled: (String s) => s.startsWith('I'),
    onChanged: print,
    selectedItems: ["Brazil"]),

customize showed field (itemAsString)

DropdownSearch<UserModel>(
  label: "Name",
  onFind: (String filter) => getData(filter),
  itemAsString: (UserModel u) => u.userAsStringByName(),
  onChanged: (UserModel data) => print(data),
),

DropdownSearch<UserModel>(
  label: "Name",
  onFind: (String filter) => getData(filter),
  itemAsString: (UserModel u) => u.userAsStringById(),
  onChanged: (UserModel data) => print(data),
),

customize Filter Function

DropdownSearch<UserModel>(
  label: "Name",
  filterFn: (user, filter) => user.userFilterByCreationDate(filter),
  onFind: (String filter) => getData(filter),
  itemAsString: (UserModel u) => u.userAsStringByName(),
  onChanged: (UserModel data) => print(data),
),

customize Search Mode

DropdownSearch<UserModel>(
  mode: Mode.BOTTOM_SHEET,
  label: "Name",
  onFind: (String filter) => getData(filter),
  itemAsString: (UserModel u) => u.userAsString(),
  onChanged: (UserModel data) => print(data),
),

Validation

DropdownSearch(
  items: ["Brazil", "France", "Tunisia", "Canada"],
  label: "Country",
  onChanged: print,
  selectedItem: "Tunisia",
  validator: (String item) {
    if (item == null)
      return "Required field";
    else if (item == "Brazil")
      return "Invalid item";
    else
      return null;
  },
);

Endpoint implementation (using Dio package)

DropdownSearch<UserModel>(
  label: "Name",
  onFind: (String filter) async {
    var response = await Dio().get(
        "http://5d85ccfb1e61af001471bf60.mockapi.io/user",
        queryParameters: {"filter": filter},
    );
    var models = UserModel.fromJsonList(response.data);
    return models;
  },
  onChanged: (UserModel data) {
    print(data);
  },
);

Layout customization

You can customize the layout of the DropdownSearch and its items. EXAMPLE

PropertiesDescription
labelDropDownSearch label
showSearchBoxshow/hide the search box
isFilteredOnlinetrue if the filter on items is applied onlie (via API)
showClearButtonshow/hide clear selected item
itemsoffline items list
selectedItemselected item
onFindfunction that returns item from API
onChangedcalled when a new item is selected
dropdownBuilderto customize list of items UI
popupItemBuilderto customize selected item
validatorfunction to apply the validation formula
searchBoxDecorationdecoration for the search box
popupBackgroundColorbackground color for the dialog/menu/bottomSheet
popupTitleCustom widget for the popup title
itemAsStringcustomize the fields the be shown
filterFncustom filter function
enabledenable/disable dropdownSearch
modeMENU / DIALOG/ BOTTOM_SHEET
maxHeightthe max height for dialog/bottomSheet/Menu
dialogMaxWidththe max width for the dialog
showSelectedItemmanage selected item visibility (if true, the selected item will be highlighted)
compareFnFunction(T item, T selectedItem), custom comparing function
dropdownSearchDecorationDropdownSearch input decoration
emptyBuildercustom layout for empty results
loadingBuildercustom layout for loading items
errorBuildercustom layout for error
autoFocusSearchBoxthe search box will be focused if true
popupShapecustom shape for the popup
autoValidateModehandle auto validation mode
onSavedAn optional method to call with the final value when the form is saved via
validatorAn optional method that validates an input. Returns an error string to display if the input is invalid, or null otherwise.
clearButtoncustomize clear button widget
clearButtonSplashRadiuscustomize clear button splash radius
dropDownButtoncustomize dropdown button widget
dropDownButtonSplashRadiuscustomize dropdown button splash radius
dropdownBuilderSupportsNullItemIf true, the dropdownBuilder will continue the uses of material behavior. This will be useful if you want to handle a custom UI only if the item !=null
popupItemDisableddefines if an item of the popup is enabled or not, if the item is disabled, it cannot be clicked
popupBarrierColorset a custom color for the popup barrier
searchBoxControllersearch box controller
clearButtonBuildercustom clear button builder
dropdownButtonBuildercustom dropdown button builder
onBeforeChangecallback executed before applying value change
searchDelaydelay before searching
popupSafeAreaset properties of popup safe area
scrollbarPropsscrollbar properties
popupBarrierDismissiblewhether modal can be dismissed by tapping the modal barrier

Attention

To use a template as an item type, and you don't want to use a custom function itemAsString and compareFn you need to implement toString, equals and hashcode, as shown below:

class UserModel {
  final String id;
  final DateTime createdAt;
  final String name;
  final String avatar;

  UserModel({this.id, this.createdAt, this.name, this.avatar});

  factory UserModel.fromJson(Map<String, dynamic> json) {
    if (json == null) return null;
    return UserModel(
      id: json["id"],
      createdAt:
          json["createdAt"] == null ? null : DateTime.parse(json["createdAt"]),
      name: json["name"],
      avatar: json["avatar"],
    );
  }

  static List<UserModel> fromJsonList(List list) {
    if (list == null) return null;
    return list.map((item) => UserModel.fromJson(item)).toList();
  }

  ///this method will prevent the override of toString
  String userAsString() {
    return '#${this.id} ${this.name}';
  }

  ///this method will prevent the override of toString
  bool userFilterByCreationDate(String filter) {
    return this?.createdAt?.toString()?.contains(filter);
  }

  ///custom comparing function to check if two users are equal
  bool isEqual(UserModel model) {
    return this?.id == model?.id;
  }

  @override
  String toString() => name;
}

View more Examples

Support

If this plugin was useful to you, helped you to deliver your app, saved you a lot of time, or you just want to support the project, I would be very grateful if you buy me a cup of coffee.

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add dropdown_search

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  dropdown_search: ^1.0.0

Alternatively, your editor might support or flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:dropdown_search/dropdown_search.dart'; 

example/lib/main.dart

import 'package:dio/dio.dart';
import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/material.dart';

import 'user_model.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'dropdownSearch Demo',
      //enable this line if you want test Dark Mode
      //theme: ThemeData.dark(),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _formKey = GlobalKey<FormState>();
  final _openDropDownProgKey = GlobalKey<DropdownSearchState<String>>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("DropdownSearch Demo")),
      body: Padding(
        padding: const EdgeInsets.all(25),
        child: Form(
          key: _formKey,
          autovalidateMode: AutovalidateMode.onUserInteraction,
          child: ListView(
            padding: EdgeInsets.all(4),
            children: <Widget>[
              ///Menu Mode with no searchBox MultiSelection
              DropdownSearch<String>.multiSelection(
                validator: (List<String>? v) {
                  return v == null || v.isEmpty ? "required field" : null;
                },
                hint: "Select a country",
                mode: Mode.MENU,
                showSelectedItems: false,
                items: ["Brazil", "Italia (Disabled)", "Tunisia", 'Canada'],
                label: "Menu mode multiSelection*",
                showClearButton: true,
                onChange: print,
                popupSelectionWidget: (cnt, String item, bool isSelected) {
                  return isSelected
                      ? Icon(
                          Icons.check_circle,
                          color: Colors.green[500],
                        )
                      : Container();
                },
                popupItemDisabled: (String s) => s.startsWith('I'),
                clearButtonSplashRadius: 20,
                selectedItems: ["Tunisia"],
              ),
              Divider(),

              ///Menu Mode with no searchBox
              DropdownSearch<String>(
                validator: (v) => v == null ? "required field" : null,
                hint: "Select a country",
                mode: Mode.MENU,
                showSelectedItems: true,
                items: ["Brazil", "Italia (Disabled)", "Tunisia", 'Canada'],
                label: "Menu mode *",
                showClearButton: true,
                onChanged: print,
                popupItemDisabled: (String? s) => s?.startsWith('I') ?? false,
                clearButtonSplashRadius: 20,
                selectedItem: "Tunisia",
                onBeforeChange: (a, b) {
                  if (b == null) {
                    AlertDialog alert = AlertDialog(
                      title: Text("Are you sure..."),
                      content: Text("...you want to clear the selection"),
                      actions: [
                        TextButton(
                          child: Text("OK"),
                          onPressed: () {
                            Navigator.of(context).pop(true);
                          },
                        ),
                        TextButton(
                          child: Text("NOT OK"),
                          onPressed: () {
                            Navigator.of(context).pop(false);
                          },
                        ),
                      ],
                    );

                    return showDialog<bool>(
                        context: context,
                        builder: (BuildContext context) {
                          return alert;
                        });
                  }

                  return Future.value(true);
                },
              ),
              Divider(),

              ///Menu Mode with overriden icon and dropdown buttons
              Row(
                children: [
                  Expanded(
                    flex: 2,
                    child: DropdownSearch<String>(
                      validator: (v) => v == null ? "required field" : null,
                      hint: "Select a country",
                      mode: Mode.MENU,
                      dropdownSearchDecoration: InputDecoration(
                        filled: true,
                        border: UnderlineInputBorder(
                          borderSide: BorderSide(color: Color(0xFF01689A)),
                        ),
                      ),
                      showAsSuffixIcons: true,
                      clearButtonBuilder: (_) => Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: const Icon(
                          Icons.clear,
                          size: 24,
                          color: Colors.black,
                        ),
                      ),
                      dropdownButtonBuilder: (_) => Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: const Icon(
                          Icons.arrow_drop_down,
                          size: 24,
                          color: Colors.black,
                        ),
                      ),
                      showSelectedItems: true,
                      items: [
                        "Brazil",
                        "Italia (Disabled)",
                        "Tunisia",
                        'Canada'
                      ],
                      label: "Menu mode *",
                      showClearButton: true,
                      onChanged: print,
                      popupItemDisabled: (String? s) =>
                          s?.startsWith('I') ?? true,
                      selectedItem: "Tunisia",
                    ),
                  ),
                  Expanded(
                      child: TextField(
                    decoration: InputDecoration(
                      filled: true,
                      labelText: "Menu mode *",
                      border: UnderlineInputBorder(
                        borderSide: BorderSide(color: Color(0xFF01689A)),
                      ),
                    ),
                  ))
                ],
              ),
              Divider(),
              DropdownSearch<UserModel>.multiSelection(
                searchFieldProps: TextFieldProps(
                  controller: TextEditingController(text: 'Mrs'),
                ),
                mode: Mode.BOTTOM_SHEET,
                maxHeight: 700,
                isFilteredOnline: true,
                showClearButton: true,
                showSelectedItems: true,
                compareFn: (item, selectedItem) => item?.id == selectedItem?.id,
                showSearchBox: true,
                label: 'User *',
                dropdownSearchDecoration: InputDecoration(
                  filled: true,
                  fillColor: Theme.of(context).inputDecorationTheme.fillColor,
                ),
                autoValidateMode: AutovalidateMode.onUserInteraction,
                validator: (u) =>
                    u == null || u.isEmpty ? "user field is required " : null,
                onFind: (String? filter) => getData(filter),
                onChange: (data) {
                  print(data);
                },
                dropdownBuilder: _customDropDownExampleMultiSelection,
                popupItemBuilder: _customPopupItemBuilderExample,
                popupSafeArea: PopupSafeArea(top: true, bottom: true),
                scrollbarProps: ScrollbarProps(
                  isAlwaysShown: true,
                  thickness: 7,
                ),
              ),
              Divider(),

              ///custom itemBuilder and dropDownBuilder
              DropdownSearch<UserModel>(
                showSelectedItems: true,
                compareFn: (i, s) => i?.isEqual(s) ?? false,
                label: "Person",
                onFind: (String? filter) => getData(filter),
                onChanged: (data) {
                  print(data);
                },
                dropdownBuilder: _customDropDownExample,
                popupItemBuilder: _customPopupItemBuilderExample2,
              ),
              Divider(),

              ///BottomSheet Mode with no searchBox
              DropdownSearch<String>(
                mode: Mode.BOTTOM_SHEET,
                items: [
                  "Brazil",
                  "Italia",
                  "Tunisia",
                  'Canada',
                  'Zraoua',
                  'France',
                  'Belgique'
                ],
                label: "Custom BottomShet mode",
                onChanged: print,
                selectedItem: "Brazil",
                showSearchBox: true,
                searchFieldProps: TextFieldProps(
                  decoration: InputDecoration(
                    border: OutlineInputBorder(),
                    contentPadding: EdgeInsets.fromLTRB(12, 12, 8, 0),
                    labelText: "Search a country1",
                  ),
                ),
                popupTitle: Container(
                  height: 50,
                  decoration: BoxDecoration(
                    color: Theme.of(context).primaryColorDark,
                    borderRadius: BorderRadius.only(
                      topLeft: Radius.circular(20),
                      topRight: Radius.circular(20),
                    ),
                  ),
                  child: Center(
                    child: Text(
                      'Country',
                      style: TextStyle(
                        fontSize: 24,
                        fontWeight: FontWeight.bold,
                        color: Colors.white,
                      ),
                    ),
                  ),
                ),
                popupShape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.only(
                    topLeft: Radius.circular(24),
                    topRight: Radius.circular(24),
                  ),
                ),
              ),
              Divider(),

              ///show favorites on top list
              DropdownSearch<UserModel>(
                showSelectedItems: true,
                showSearchBox: true,
                compareFn: (i, s) => i?.isEqual(s) ?? false,
                label: "Person with favorite option",
                onFind: (filter) => getData(filter),
                onChanged: (data) {
                  print(data);
                },
                dropdownBuilder: _customDropDownExample,
                popupItemBuilder: _customPopupItemBuilderExample2,
                showFavoriteItems: true,
                favoriteItemsAlignment: MainAxisAlignment.start,
                favoriteItems: (items) {
                  return items.where((e) => e.name.contains("Mrs")).toList();
                },
                favoriteItemBuilder: (context, item) {
                  return Container(
                    padding: EdgeInsets.symmetric(horizontal: 8, vertical: 6),
                    decoration: BoxDecoration(
                        border: Border.all(color: Colors.grey),
                        borderRadius: BorderRadius.circular(10),
                        color: Colors.grey[100]),
                    child: Text(
                      "${item.name}",
                      textAlign: TextAlign.center,
                      style: TextStyle(color: Colors.indigo),
                    ),
                  );
                },
              ),
              Divider(),

              ///merge online and offline data in the same list and set custom max Height
              DropdownSearch<UserModel>(
                items: [
                  UserModel(name: "Offline name1", id: "999"),
                  UserModel(name: "Offline name2", id: "0101")
                ],
                maxHeight: 300,
                onFind: (String? filter) => getData(filter),
                label: "choose a user",
                onChanged: print,
                showSearchBox: true,
              ),
              Divider(),

              ///open dropdown programmatically
              DropdownSearch<String>(
                items: ["no action", "confirm in the next dropdown"],
                label: "open another dropdown programmatically",
                onChanged: (v) {
                  if (v == "confirm in the next dropdown") {
                    _openDropDownProgKey.currentState?.openDropDownSearch();
                  }
                },
              ),
              Padding(padding: EdgeInsets.all(4)),
              DropdownSearch<String>(
                key: _openDropDownProgKey,
                items: ["Yes", "No"],
                label: "confirm",
                showSelectedItems: true,
                dropdownButtonSplashRadius: 20,
              ),
              Column(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                mainAxisSize: MainAxisSize.min,
                children: [
                  ElevatedButton(
                      onPressed: () {
                        _openDropDownProgKey.currentState?.openDropDownSearch();
                      },
                      child: Text("Open dropdownSearch")),
                  ElevatedButton(
                      onPressed: () {
                        _openDropDownProgKey.currentState
                            ?.changeSelectedItem("No");
                      },
                      child: Text("set to 'NO'")),
                  Material(
                    child: ElevatedButton(
                        onPressed: () {
                          _openDropDownProgKey.currentState
                              ?.changeSelectedItem("Yes");
                        },
                        child: Text("set to 'YES'")),
                  ),
                  ElevatedButton(
                      onPressed: () {
                        _openDropDownProgKey.currentState
                            ?.changeSelectedItem("Blabla");
                      },
                      child: Text("set to 'Blabla'")),
                ],
              )
            ],
          ),
        ),
      ),
    );
  }

  Widget _customDropDownExampleMultiSelection(
      BuildContext context, List<UserModel?> selectedItems) {
    if (selectedItems.isEmpty) {
      return ListTile(
        contentPadding: EdgeInsets.all(0),
        leading: CircleAvatar(),
        title: Text("No item selected"),
      );
    }

    return Wrap(
      children: selectedItems.map((e) {
        return Padding(
          padding: const EdgeInsets.all(4.0),
          child: Container(
            child: ListTile(
              contentPadding: EdgeInsets.all(0),
              leading: CircleAvatar(
                  // this does not work - throws 404 error
                  // backgroundImage: NetworkImage(item.avatar ?? ''),
                  ),
              title: Text(e?.name ?? ''),
              subtitle: Text(
                e?.createdAt.toString() ?? '',
              ),
            ),
          ),
        );
      }).toList(),
    );
  }

  Widget _customDropDownExample(BuildContext context, UserModel? item) {
    if (item == null) {
      return Container();
    }

    return Container(
      child: (item.avatar == null)
          ? ListTile(
              contentPadding: EdgeInsets.all(0),
              leading: CircleAvatar(),
              title: Text("No item selected"),
            )
          : ListTile(
              contentPadding: EdgeInsets.all(0),
              leading: CircleAvatar(
                  // this does not work - throws 404 error
                  // backgroundImage: NetworkImage(item.avatar ?? ''),
                  ),
              title: Text(item.name),
              subtitle: Text(
                item.createdAt.toString(),
              ),
            ),
    );
  }

  Widget _customPopupItemBuilderExample(
      BuildContext context, UserModel? item, bool isSelected) {
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 8),
      decoration: !isSelected
          ? null
          : BoxDecoration(
              border: Border.all(color: Theme.of(context).primaryColor),
              borderRadius: BorderRadius.circular(5),
              color: Colors.white,
            ),
      child: ListTile(
        selected: isSelected,
        title: Text(item?.name ?? ''),
        subtitle: Text(item?.createdAt?.toString() ?? ''),
        leading: CircleAvatar(
            // this does not work - throws 404 error
            // backgroundImage: NetworkImage(item.avatar ?? ''),
            ),
      ),
    );
  }

  Widget _customPopupItemBuilderExample2(
      BuildContext context, UserModel? item, bool isSelected) {
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 8),
      decoration: !isSelected
          ? null
          : BoxDecoration(
              border: Border.all(color: Theme.of(context).primaryColor),
              borderRadius: BorderRadius.circular(5),
              color: Colors.white,
            ),
      child: ListTile(
        selected: isSelected,
        title: Text(item?.name ?? ''),
        subtitle: Text(item?.createdAt?.toString() ?? ''),
        leading: CircleAvatar(
            // this does not work - throws 404 error
            // backgroundImage: NetworkImage(item.avatar ?? ''),
            ),
      ),
    );
  }

  Future<List<UserModel>> getData(filter) async {
    var response = await Dio().get(
      "https://5d85ccfb1e61af001471bf60.mockapi.io/user",
      queryParameters: {"filter": filter},
    );

    final data = response.data;
    if (data != null) {
      return UserModel.fromJsonList(data);
    }

    return [];
  }
} 

Download Details:

Author: salim-lachdhaf

Source Code: https://github.com/salim-lachdhaf/searchable_dropdown

#flutter  #dropdown 

What is GEEK

Buddha Community

Flutter Simple and Robust DropdownSearch with Item Search Feature
伊藤  直子

伊藤 直子

1647732000

最高のCSSグリッドジェネレーターの比較

グリッド、グリッド、グリッド。それらを使ってできることはたくさんあります。しかし、覚えておかなければならない多くのプロパティ。😅

あなたが私のようで、グリッドを使用するときに常にGoogleに頼らなければならない場合、このガイドで説明するトリックは、開発者としてのあなたの生活をはるかに楽にします。

CSSグリッドジェネレーターとは何ですか?

グリッドジェネレーターは、数回クリックするだけでグリッドを生成するために使用できるWebサイトです。しかし、なぜあなたはそれらを気にする必要がありますか?私の場合、Webサイトのレイアウトや、インターフェイス内の複雑なレスポンシブ構造を設計するときに、これらを頻繁に使用します。グリッドは、わずか数行のCSSで多くのことを達成するのに役立ち、多くの時間を節約できるので素晴らしいです。

この記事では、次のCSSグリッドジェネレーターを比較し、それらの長所と短所を一覧表示して、お気に入りのものをブックマークできるようにします。

  • CSSグリッドジェネレーター
  • CSSレイアウトジェネレーター
  • グリッドLayoutIt
  • グリディ
  • Cssgr.id
  • AngryToolsCSSグリッド

また、時間を節約するために、覚えておく必要のある重要なCSSグリッドプロパティを使用してチートシートを作成しました。🥳このチートシートは、この記事の下部にあります。

1.CSSグリッドジェネレーター

CSSグリッドジェネレーターを最もよく使用するので、リストの最初に置きます。これはSarahDrasnerによって設計されたオープンソースプロジェクトです(プロジェクトのコードは、貢献したい場合はここから入手できます)。

例を挙げると、最近、2行3列の単純なグリッドを生成する必要がありました。行ギャップと列ギャップに特定のサイズを設定する方法を覚えていませんでした。CSS Grid Generatorを使用すると、必要な構造を簡単に作成して、より複雑なタスクに進むことができました。

.parent {表示:グリッド; grid-template-columns:repeat(3、1fr); grid-template-rows:repeat(2、1fr); grid-column-gap:60px; grid-row-gap:30px; }

最終的なグリッドは次のようになりました。

長所:

  • インターフェイスはユーザーフレンドリーで、色も適切に選択されているため、CSSグリッドジェネレーターはCSSグリッドに慣れたい初心者にとって優れたツールです。
  • CSSグリッドジェネレーターは、グリッド全体の列、行、およびギャップの数を指定できるため、ほとんどのユースケースで必要な結果を得るのに役立ちます。
  • ボタンを1つ押すだけで、コードをプレビューしてクリップボードにコピーできます

短所:

  • 時間を節約するために選択できるテンプレートはありません
  • 複雑なレイアウトを生成することはできません

2.CSSレイアウトジェネレーター

CSSレイアウトジェネレーターをリストの最初に置くこともできます。常に複雑なグリッドを生成する場合は、これをブックマークする必要があります。ブレードデザインシステムによって開発されたCSSレイアウトジェネレーターは、ほとんどの頭痛の種を解決する幅広いオプションを提供します。

私の日常業務では、CSSレイアウトジェネレーターテンプレートを頻繁に使用します。これは、サイドバー/コンテナーまたはヘッダー/メイン/フッターのある構造を便利に選択できるためです。

<section class="layout">
  <!-- The left sidebar where you can put your navigation items etc. -->
  <div class="sidebar">1</div>

  <!-- The main content of your website -->
  <div class="body">2</div>
</section>

<style>
.layout {
  width: 1366px;
  height: 768px;
  display: grid;
  /* This is the most important part where we define the size of our sidebar and body  */
  grid:
    "sidebar body" 1fr
    / auto 1fr;
  gap: 8px;
}

.sidebar {
  grid-area: sidebar;
}

.body {
  grid-area: body;
}
</style>

サイドバーオプションは次のようになります。

長所:

  • CSS Layout Generatorを使用すると、6つの標準テンプレートから選択してより早く開始できます
  • ほぼすべてのユースケースを解決するための多くのオプションがあります
  • グリッドとFlexboxを切り替えることができます。これは、両方のオプションを比較するのに役立ちます
  • インターフェースは素晴らしく、ユーザーフレンドリーです

短所:

  • それは非常に多くのオプションを提供するので、CSSレイアウトジェネレータは初心者にとって混乱する可能性があります

3.グリッドLayoutIt

グリッドレイアウトこれはLeniolabsによって開発されたもので、多くのオプションを備えたもう1つのグリッドジェネレーターです。貢献に興味がある場合は、コードをGitHubで公開しています。

先週、顧客から、製品に関する重要なメトリックを表示するためのインターフェイスを設計するように依頼されました(Geckoboardに多少似ています)。彼が望んでいたレイアウトは非常に正確でしたが、LayoutItのおかげで、数秒でコードを生成できました。

<div class="container">
  <div class="metric-1"></div>
  <div class="metric-2"></div>
  <div class="metrics-3"></div>
  <div class="metric-4"></div>
  <div class="metric-5"></div>
  <div class="metric-6"></div>
</div>

<style>
.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  gap: 20px 20px;
  grid-auto-flow: row;
  grid-template-areas:
    "metric-1 metric-1 metric-2"
    "metrics-3 metric-4 metric-2"
    "metric-5 metric-5 metric-6";
}
.metric-1 {
  grid-area: metric-1;
}
.metric-2 {
  grid-area: metric-2;
}
.metrics-3 {
  grid-area: metrics-3;
}
.metric-4 {
  grid-area: metric-4;
}
.metric-5 {
  grid-area: metric-5;
}
.metric-6 {
  grid-area: metric-6;
}
</style>

結果のレイアウトは次のようになります。

長所:

  • グリッドレイアウト直感的に使用でき、多くのオプションを提供します
  • ピクセル(px)、フラクショナル(fr)、およびパーセンテージ(%)を使用して、列と行を設定できます。
  • レイアウトは、ワンクリックでCodePen、CodeSandbox、またはStackBlitzにエクスポートできます
  • インターフェースは適切に設計されており、オプションとグリッドプレビューの間に適切なコントラストがあります。
  • グリッドレイアウトグリッド配置オプションをサポート

短所:

  • このジェネレーターは、時間を節約するためのテンプレートを提供していません。これが、リストの3番目に配置した主な理由です。

4.グリディ

私の過去の経験では、Griddyを使用して多くの時間を費やしました。Sarah Drasnerによって作成されたCSSグリッドよりも使いやすさは少し劣りますが、より多くのオプションが提供されます。

たとえば、次の3行の4列グリッドを簡単に生成できます。

.container {
  display: grid;
  grid-template-columns: 1fr 300px 1fr 1fr;
  grid-template-rows: 2fr 100px 1fr;
  grid-column-gap: 10px
  grid-row-gap: 20px
  justify-items: stretch
  align-items: stretch
}

結果のレイアウトは次のようになります。

長所:

  • ピクセル(px)、フラクショナル(fr)、およびパーセンテージ(%)を使用して、列と行を設定できます。
  • 提供されているオプションは、ほとんどのユースケースを解決し、さまざまな配置をテストするのに十分です。一言で言えば、それは仕事を成し遂げます

短所:

  • 好みの問題かもしれませんが、オプション付きのサイドバーは私にとって最適なインターフェイスではありません。探しているものを取得するには、しばらくスクロールする必要があります
  • 選択できるテンプレートはありません
  • minmax()機能はありません

5. Cssgr.id

Cssgr.idは、オプションが多すぎないが、ほとんどのユースケースを解決するのに十分なグリッドジェネレーターを探している場合のもう1つの優れた選択肢です。

ギャラリーテンプレートがあることを思い出したので、昨年Cssgr.idを使用してギャラリーを作成しました。数回クリックするだけで、必要なものに非常に近いものを得ることができました。

<div class="grid">
  <!-- This item will take 3 columns and 2 rows -->
  <div class="span-col-3 span-row-2">Item 1</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 2</div>
  <div class="span-row-2">Item 3</div>
  <div class="span-row-3">Item 4</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 5</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 6</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 7</div>

  <!-- This item will take 3 columns and 2 rows -->
  <div class="span-col-3 span-row-2">Item 8</div>

  <!-- This item will take 2 columns and 3 rows -->
  <div class="span-col-2 span-row-2">Item 9</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 10</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 11</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 12</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 13</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 14</div>
</div>

<style>
.grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-gap: 10px;
}

/* Items with this class will take 3 columns */
.span-col-3 {
  grid-column: span 3 / auto;
}

/* Items with this class will take 2 columns */
.span-col-2 {
  grid-column: span 2 / auto;
}

/* Items with this class will take 2 rows */
.span-row-2 {
  grid-row: span 2 / auto;
}

/* Items with this class will take 3 rows */
.span-row-3 {
  grid-row: span 3 / auto;
}
</style>

ギャラリーは次のようになりました。

長所:

  • Cssgr.idには、5つの実用的なスターターレイアウト(3×3、サッカーフォーメーション、ヘッダー/フッター、ギャラリー、および一般的なWebサイト)から選択できます。
  • プレースホルダーテキストを追加して、書かれたコンテンツでどのようにレンダリングされるかを確認できます
  • 簡単に設定できる適切に設計されたインターフェイスを備えています

短所:

  • ほとんどのオプションを備えたグリッドジェネレータではありません

6. AngryToolsCSSグリッド

Angry Tools CSSグリッドは、リストの最後のCSSグリッドジェネレーターです。このガイドで強調表示されている他のツールよりもユーザーフレンドリーではないかもしれませんが、便利な場合があります。

Angry Tools CSSグリッドは、ギャラリーを生成するときにも役立ちます。正方形をクリックすると、サイズと方向(水平または垂直)を定義できます。

<div class="angry-grid">
  <div id="item-0">Item 0</div>
  <div id="item-1">Item 1</div>
  <div id="item-2">Item 2</div>
  <div id="item-3">Item 3</div>
  <div id="item-4">Item 4</div>
  <div id="item-5">Item 5</div>
  <div id="item-6">Item 6</div>
  <div id="item-7">Item 7</div>
  <div id="item-8">Item 8</div>
  <div id="item-9">Item 9</div>
</div>

<style>
.angry-grid {
  display: grid;
  /* Our grid will be displayed using 3 rows */
  grid-template-rows: 1fr 1fr 1fr;
  /* Our grid will be displayed using 4 columns */
  grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
  /* You can define a gap between your columns and your rows if you need to */
  gap: 0px;
  height: 100%;
}

/* This grid item will start at row 1 and column 4 and end at row 2 and column 5 */
#item-0 {
  background-color: #8bf7ba;
  grid-row-start: 1;
  grid-column-start: 4;
  grid-row-end: 2;
  grid-column-end: 5;
}

/* This grid item will start at row 2 and column 3 and end at row 3 and column 5 */
#item-1 {
  background-color: #bf9aa7;
  grid-row-start: 2;
  grid-column-start: 3;
  grid-row-end: 3;
  grid-column-end: 5;
}

/* This grid item will start at row 2 and column 2 and end at row 3 and column 3 */
#item-2 {
  background-color: #c7656e;
  grid-row-start: 2;
  grid-column-start: 2;
  grid-row-end: 3;
  grid-column-end: 3;
}

/* This grid item will start at row 1 and column 1 and end at row 2 and column 3 */
#item-3 {
  background-color: #b659df;
  grid-row-start: 1;
  grid-column-start: 1;
  grid-row-end: 2;
  grid-column-end: 3;
}

/* This grid item will start at row 3 and column 1 and end at row 4 and column 3 */
#item-4 {
  background-color: #be6b5e;
  grid-row-start: 3;
  grid-column-start: 1;
  grid-row-end: 4;
  grid-column-end: 3;
}

/* This grid item will start at row 3 and column 4 and end at row 4 and column 6 */
#item-5 {
  background-color: #5bb9d7;
  grid-row-start: 3;
  grid-column-start: 4;
  grid-row-end: 4;
  grid-column-end: 6;
}

/* This grid item will start at row 1 and column 5 and end at row 3 and column 6 */
#item-6 {
  background-color: #56adba;
  grid-row-start: 1;
  grid-column-start: 5;
  grid-row-end: 3;
  grid-column-end: 6;
}

/* This grid item will start at row 1 and column 3 and end at row 2 and column 4 */
#item-7 {
  background-color: #9cab58;
  grid-row-start: 1;
  grid-column-start: 3;
  grid-row-end: 2;
  grid-column-end: 4;
}

/* This grid item will start at row 3 and column 3 and end at row 4 and column 4 */
#item-8 {
  background-color: #8558ad;
  grid-row-start: 3;
  grid-column-start: 3;
  grid-row-end: 4;
  grid-column-end: 4;
}

/* This grid item will start at row 2 and column 1 and end at row 3 and column 2 */
#item-9 {
  background-color: #96b576;
  grid-row-start: 2;
  grid-column-start: 1;
  grid-row-end: 3;
  grid-column-end: 2;
}
</style>

結果のギャラリーは次のようになります。

長所:

  • Angry Tools CSS Gridには、選択可能ないくつかのテンプレートが付属しています

短所:

  • 全体的に最高のデザインではありません。正直なところ、それはかなり醜く、使いにくいことがあります
  • 初心者にはお勧めしません。上級開発者は、おそらく代わりにCSSLayoutGeneratorまたはGridLayoutItのいずれかを選択する必要があります
  • CSS出力を取得するにはスクロールする必要があります

ボーナス:CSSグリッドチートシート

CSSグリッドジェネレーターは、CSSプロパティに慣れていない場合に最適です。ただし、より高度な開発者になると、簡単なチートシートの方がおそらく便利な場合があります。

😇それがあなたを助けることができるなら、これが私が自分のために作ったものです:

gap行と列の間のギャップサイズを設定します。これは、次のプロパティの省略形ですrow-gapcolumn-gap
row-gapグリッド行間のギャップを指定します
column-gap列間のギャップを指定します
gridgrid-template-rowsの省略grid-template-columns形プロパティ:grid-template-areas、、、、、、grid-auto-rowsgrid-auto-columnsgrid-auto-flow
grid-areaグリッドレイアウトでのグリッドアイテムのサイズと位置を指定します。これは、次のプロパティの省略形のプロパティです:grid-row-start、、、grid-column-startgrid-row-endgrid-column-end
grid-auto-columnsグリッドコンテナの列のサイズを設定します
grid-auto-flow自動配置されたアイテムをグリッドに挿入する方法を制御します
grid-auto-rowsグリッドコンテナの行のサイズを設定します
grid-columnグリッドレイアウトでのグリッドアイテムのサイズと位置を指定します。これは、次のプロパティの省略形のプロパティです。grid-column-startgrid-column-end
grid-column-endアイテムがまたがる列の数、またはアイテムが終了する列行を定義します
grid-column-gapグリッドレイアウトの列間のギャップのサイズを定義します
grid-column-startアイテムが開始する列行を定義します
grid-gapグリッドレイアウトの行と列の間のギャップのサイズを定義し、次のプロパティの省略形のプロパティです。grid-row-gapgrid-column-gap
grid-rowグリッドレイアウトでのグリッドアイテムのサイズと位置を指定します。これは、次のプロパティの省略形のプロパティです。grid-row-startgrid-row-end
grid-row-endアイテムがまたがる行数、またはアイテムが終了する行行を定義します
grid-row-gapグリッドレイアウトの行間のギャップのサイズを定義します
grid-row-startアイテムが開始する行行を定義します
grid-template次のプロパティの省略形プロパティ:grid-template-rows、、grid-template-columnsgrid-template-areas
grid-template-areasグリッドレイアウト内の領域を指定します
grid-template-columnsグリッドレイアウトの列の数(および幅)を指定します
grid-template-rowsグリッドレイアウトの行の数(および高さ)を指定します

最高のCSSグリッドジェネレーターのこの簡単な比較が、お気に入りのジェネレーターをブックマークするのに役立つことを願っています。

また、CSSグリッドを扱うときに重要なアドバイスを提供できる場合は、時間をかけてください。これらのジェネレーターは、必要なレイアウトを段階的に取得し、複雑なソリューションに依存することを回避するのに役立つため、優れたオプションです。

読んでくれてありがとう!  

ソース:https ://blog.logrocket.com/comparing-best-css-grid-generators/

#css 

Comparing the best CSS grid generators

Grids, grids, grids. So many things we can do with them. But, so many properties we have to remember. 😅

If you are like me and you always have to resort to Google when using grids, the tricks we’ll cover in this guide will make your life as a developer much easier.

What are CSS grid generators?

A grid generator is a website you can use to generate a grid in a few clicks. But why should you care about them? In my case, I use them quite often when I want to design the layout of my websites or a complex responsive structure inside an interface. Grids are great because they help you achieve a lot with just a few CSS lines, which saves a lot of time.

In this article, we will compare the following CSS grid generators and list their pros and cons so that you can bookmark your favorite one:

  • CSS Grid Generator
  • CSS Layout Generator
  • Grid LayoutIt
  • Griddy
  • Cssgr.id
  • Angry Tools CSS Grid

Also, to save you time, I made a cheat sheet with the essential CSS grid properties you should remember. 🥳 This cheat sheet is available at the bottom of this article.

1. CSS Grid Generator

CSS Grid Generator

I put CSS Grid Generator first on my list because I use it the most. It is an open source project designed by Sarah Drasner (the code of the project is available here if you want to contribute).

To give you an example, I recently needed to generate a simple grid with two rows and three columns. I didn’t remember how to set a specific size for the row gap and the column gap. With CSS Grid Generator, I was able to easily create the structure I desired and move on to more complex tasks.

.parent {  display: grid;  grid-template-columns: repeat(3, 1fr);  grid-template-rows: repeat(2, 1fr);  grid-column-gap: 60px;  grid-row-gap: 30px; }

The final grid looked like this:

Example Of CSS Grid Generator

Pros:

  • The interface is user-friendly and the colors are well-chosen, making CSS Grid Generator an excellent tool for beginners who want to become more familiar with CSS grids
  • CSS Grid Generator can help you get the result you want for most use cases because you can specify the number of columns, rows, and gaps across your grids
  • Just hit one button to preview the code and copy it to your clipboard

Cons:

  • There is no template you can choose to save you time
  • You will not be able to generate complicated layouts

2. CSS Layout Generator

CSS Layout Generator

I could have put CSS Layout Generator first on the list. If you are looking to generate complicated grids all the time, this is probably the one you should bookmark. Developed by Braid Design System, CSS Layout Generator offers a wide range of options that will solve most headaches.

In my daily work, I use CSS Layout Generator templates a lot because they conveniently allow you to choose between a structure with a sidebar/container or a header/main/footer.

<section class="layout">
  <!-- The left sidebar where you can put your navigation items etc. -->
  <div class="sidebar">1</div>

  <!-- The main content of your website -->
  <div class="body">2</div>
</section>

<style>
.layout {
  width: 1366px;
  height: 768px;
  display: grid;
  /* This is the most important part where we define the size of our sidebar and body  */
  grid:
    "sidebar body" 1fr
    / auto 1fr;
  gap: 8px;
}

.sidebar {
  grid-area: sidebar;
}

.body {
  grid-area: body;
}
</style>

The Sidebar option looks like this:

Example Of CSS Layout Generator

Pros:

  • CSS Layout Generator allows you to choose between six standard templates to get started faster
  • There are many options to solve nearly all use cases
  • You can switch between grids and Flexbox, which is helpful to compare both options
  • The interface is excellent and user-friendly

Cons:

  • Because it offers so many options, CSS Layout Generator can be confusing for a beginner

3. Grid LayoutIt

Grid LayoutIt

Grid LayoutIt was developed by Leniolabs and is another grid generator that comes with many options. The code is available publicly on GitHub if you are interested in contributing.

Last week, a customer asked me to design an interface to display important metrics about his product (somewhat similar to Geckoboard). The layout he wanted was very precise but, thanks to LayoutIt, I generated the code in a few seconds.

<div class="container">
  <div class="metric-1"></div>
  <div class="metric-2"></div>
  <div class="metrics-3"></div>
  <div class="metric-4"></div>
  <div class="metric-5"></div>
  <div class="metric-6"></div>
</div>

<style>
.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  gap: 20px 20px;
  grid-auto-flow: row;
  grid-template-areas:
    "metric-1 metric-1 metric-2"
    "metrics-3 metric-4 metric-2"
    "metric-5 metric-5 metric-6";
}
.metric-1 {
  grid-area: metric-1;
}
.metric-2 {
  grid-area: metric-2;
}
.metrics-3 {
  grid-area: metrics-3;
}
.metric-4 {
  grid-area: metric-4;
}
.metric-5 {
  grid-area: metric-5;
}
.metric-6 {
  grid-area: metric-6;
}
</style>

The resulting layout looked like this:

Example Of Grid LayoutIt

Pros:

  • Grid LayoutIt is intuitive to use and it provides many options
  • You can set your columns and your rows using pixels (px), fractionals (fr), and percentages (%)
  • Your layouts can be exported to CodePen, CodeSandbox, or StackBlitz in one click
  • The interface is well-designed, with a proper contrast between the options and the grid preview
  • Grid LayoutIt supports grid placement options

Cons:

  • This generator does not provide templates to save you time, which is the main reason why I put it third on the list

4. Griddy

Griddy

In my past experience, I spent a lot of time using Griddy. It is a little less easy to use than the CSS grid made by Sarah Drasner, but it offers more options.

For example, it allows you to easily generate a four column grid with three rows:

.container {
  display: grid;
  grid-template-columns: 1fr 300px 1fr 1fr;
  grid-template-rows: 2fr 100px 1fr;
  grid-column-gap: 10px
  grid-row-gap: 20px
  justify-items: stretch
  align-items: stretch
}

The resulting layout looks like this:

Example Of Griddy

Pros:

  • You can set your columns and your rows using pixels (px), fractionals (fr), and percentages (%)
  • The provided options are enough to solve most use cases and test different alignments. In a nutshell, it gets the job done

Cons:

  • It may be a question of taste, but the sidebar with the options is not the best interface for me. You have to scroll for a while to get what you are looking for
  • There are no templates to choose from
  • There is no minmax() function

5. Cssgr.id

CSS Grid

Cssgr.id is another great choice if you are looking for a grid generator that does not have too many options but enough to solve most use cases.

I used Cssgr.id last year to create a gallery because I remembered that it had a gallery template. In a few clicks, I was able to get something quite close to what I needed.

<div class="grid">
  <!-- This item will take 3 columns and 2 rows -->
  <div class="span-col-3 span-row-2">Item 1</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 2</div>
  <div class="span-row-2">Item 3</div>
  <div class="span-row-3">Item 4</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 5</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 6</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 7</div>

  <!-- This item will take 3 columns and 2 rows -->
  <div class="span-col-3 span-row-2">Item 8</div>

  <!-- This item will take 2 columns and 3 rows -->
  <div class="span-col-2 span-row-2">Item 9</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 10</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 11</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 12</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 13</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 14</div>
</div>

<style>
.grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-gap: 10px;
}

/* Items with this class will take 3 columns */
.span-col-3 {
  grid-column: span 3 / auto;
}

/* Items with this class will take 2 columns */
.span-col-2 {
  grid-column: span 2 / auto;
}

/* Items with this class will take 2 rows */
.span-row-2 {
  grid-row: span 2 / auto;
}

/* Items with this class will take 3 rows */
.span-row-3 {
  grid-row: span 3 / auto;
}
</style>

The gallery looked like this:

Example Of CSSGrid

Pros:

  • Cssgr.id comes with five practical starter layouts to choose from (3×3, football formation, header/footer, gallery, and generic website)
  • You can add placeholder text to see how it renders with some written content
  • It has a well-designed interface that can be easily configured

Cons:

  • It is not the grid generator with the most options

6. Angry Tools CSS Grid

Angry Tools CSS Grid

Angry Tools CSS Grid is the last CSS grid generator on our list. It can be handy, though probably less user-friendly than the other tools highlighted in this guide.

Angry Tools CSS Grid is also useful when generating galleries. By clicking on the squares, you can define their sizes and their directions (horizontally or vertically).

<div class="angry-grid">
  <div id="item-0">Item 0</div>
  <div id="item-1">Item 1</div>
  <div id="item-2">Item 2</div>
  <div id="item-3">Item 3</div>
  <div id="item-4">Item 4</div>
  <div id="item-5">Item 5</div>
  <div id="item-6">Item 6</div>
  <div id="item-7">Item 7</div>
  <div id="item-8">Item 8</div>
  <div id="item-9">Item 9</div>
</div>

<style>
.angry-grid {
  display: grid;
  /* Our grid will be displayed using 3 rows */
  grid-template-rows: 1fr 1fr 1fr;
  /* Our grid will be displayed using 4 columns */
  grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
  /* You can define a gap between your columns and your rows if you need to */
  gap: 0px;
  height: 100%;
}

/* This grid item will start at row 1 and column 4 and end at row 2 and column 5 */
#item-0 {
  background-color: #8bf7ba;
  grid-row-start: 1;
  grid-column-start: 4;
  grid-row-end: 2;
  grid-column-end: 5;
}

/* This grid item will start at row 2 and column 3 and end at row 3 and column 5 */
#item-1 {
  background-color: #bf9aa7;
  grid-row-start: 2;
  grid-column-start: 3;
  grid-row-end: 3;
  grid-column-end: 5;
}

/* This grid item will start at row 2 and column 2 and end at row 3 and column 3 */
#item-2 {
  background-color: #c7656e;
  grid-row-start: 2;
  grid-column-start: 2;
  grid-row-end: 3;
  grid-column-end: 3;
}

/* This grid item will start at row 1 and column 1 and end at row 2 and column 3 */
#item-3 {
  background-color: #b659df;
  grid-row-start: 1;
  grid-column-start: 1;
  grid-row-end: 2;
  grid-column-end: 3;
}

/* This grid item will start at row 3 and column 1 and end at row 4 and column 3 */
#item-4 {
  background-color: #be6b5e;
  grid-row-start: 3;
  grid-column-start: 1;
  grid-row-end: 4;
  grid-column-end: 3;
}

/* This grid item will start at row 3 and column 4 and end at row 4 and column 6 */
#item-5 {
  background-color: #5bb9d7;
  grid-row-start: 3;
  grid-column-start: 4;
  grid-row-end: 4;
  grid-column-end: 6;
}

/* This grid item will start at row 1 and column 5 and end at row 3 and column 6 */
#item-6 {
  background-color: #56adba;
  grid-row-start: 1;
  grid-column-start: 5;
  grid-row-end: 3;
  grid-column-end: 6;
}

/* This grid item will start at row 1 and column 3 and end at row 2 and column 4 */
#item-7 {
  background-color: #9cab58;
  grid-row-start: 1;
  grid-column-start: 3;
  grid-row-end: 2;
  grid-column-end: 4;
}

/* This grid item will start at row 3 and column 3 and end at row 4 and column 4 */
#item-8 {
  background-color: #8558ad;
  grid-row-start: 3;
  grid-column-start: 3;
  grid-row-end: 4;
  grid-column-end: 4;
}

/* This grid item will start at row 2 and column 1 and end at row 3 and column 2 */
#item-9 {
  background-color: #96b576;
  grid-row-start: 2;
  grid-column-start: 1;
  grid-row-end: 3;
  grid-column-end: 2;
}
</style>

The resulting gallery looks like this:

Example Of Angry Tools

Pros:

  • Angry Tools CSS Grid comes with some templates you can choose from

Cons:

  • It does not have the best design overall. To be honest, it is quite ugly and can be hard to use
  • I would not recommend this tool for beginners. Advanced developers should also probably choose either CSS Layout Generator or Grid LayoutIt instead
  • You have to scroll to get the CSS outputs

BONUS: CSS grid cheat sheet

CSS grid generators are great when you are not familiar with CSS properties. But, as you become a more advanced developer, you may find that a quick cheat sheet is probably handier.

😇 If it can help you, here is the one I have made for myself:

gapSets the gap size between the rows and columns. It is a shorthand for the following properties: row-gap and column-gap
row-gapSpecifies the gap between the grid rows
column-gapSpecifies the gap between the columns
gridA shorthand property for: grid-template-rows, grid-template-columns, grid-template-areas, grid-auto-rows, grid-auto-columns, grid-auto-flow
grid-areaSpecifies a grid item’s size and location in a grid layout and is a shorthand property for the following properties: grid-row-start, grid-column-start, grid-row-end, grid-column-end
grid-auto-columnsSets the size for the columns in a grid container
grid-auto-flowControls how auto-placed items get inserted in the grid
grid-auto-rowsSets the size for the rows in a grid container
grid-columnSpecifies a grid item’s size and location in a grid layout and is a shorthand property for the following properties: grid-column-start, grid-column-end
grid-column-endDefines how many columns an item will span or on which column-line the item will end
grid-column-gapDefines the size of the gap between the columns in a grid layout
grid-column-startDefines on which column-line the item will start
grid-gapDefines the size of the gap between the rows and columns in a grid layout and is a shorthand property for the following properties: grid-row-gap, grid-column-gap
grid-rowSpecifies a grid item’s size and location in a grid layout and is a shorthand property for the following properties: grid-row-start, grid-row-end
grid-row-endDefines how many rows an item will span or on which row-line the item will end
grid-row-gapDefines the size of the gap between the rows in a grid layout
grid-row-startDefines on which row-line the item will start
grid-templateA shorthand property for the following properties: grid-template-rows, grid-template-columns, grid-template-areas
grid-template-areasSpecifies areas within the grid layout
grid-template-columnsSpecifies the number (and the widths) of columns in a grid layout
grid-template-rowsSpecifies the number (and the heights) of the rows in a grid layout

I hope this quick comparison of the best CSS grid generators helped you bookmark your favorite one.

Also, if I can give you a critical piece of advice when dealing with CSS grids: take your time. These generators are a great option because they can help you get the layouts you need step by step and avoid relying on a complicated solution.

Thank you for reading!  

Source: https://blog.logrocket.com/comparing-best-css-grid-generators/

#css 

Saul  Alaniz

Saul Alaniz

1647743100

Comparando Los Mejores Generadores De Grid CSS

Rejillas, rejillas, rejillas. Tantas cosas que podemos hacer con ellos. Pero, tantas propiedades que tenemos que recordar. 😅

Si eres como yo y siempre tienes que recurrir a Google cuando usas grillas, los trucos que veremos en esta guía te harán la vida mucho más fácil como desarrollador.

¿Qué son los generadores de grid CSS?

Un generador de cuadrículas es un sitio web que puede usar para generar una cuadrícula con unos pocos clics. Pero, ¿por qué deberías preocuparte por ellos? En mi caso, los uso con bastante frecuencia cuando quiero diseñar el diseño de mis sitios web o una estructura receptiva compleja dentro de una interfaz. Las cuadrículas son geniales porque te ayudan a lograr mucho con solo unas pocas líneas CSS, lo que ahorra mucho tiempo.

En este artículo, compararemos los siguientes generadores de grillas CSS y enumeraremos sus ventajas y desventajas para que pueda marcar su favorito:

  • Generador de cuadrícula CSS
  • Generador de diseño CSS
  • Diseño de cuadrícula
  • rejilla
  • cssgr.id
  • Cuadrícula CSS de Angry Tools

Además, para ahorrarle tiempo, hice una hoja de trucos con las propiedades esenciales de la cuadrícula CSS que debe recordar. 🥳 Esta hoja de trucos está disponible al final de este artículo.

1. Generador de cuadrícula CSS

Puse CSS Grid Generator primero en mi lista porque lo uso más. Es un proyecto de código abierto diseñado por Sarah Drasner (el código del proyecto está disponible aquí si quieres contribuir).

Para darte un ejemplo, hace poco necesitaba generar una cuadrícula simple con dos filas y tres columnas. No recordaba cómo establecer un tamaño específico para el espacio entre filas y entre columnas. Con CSS Grid Generator, pude crear fácilmente la estructura que deseaba y pasar a tareas más complejas.

.parent { pantalla: cuadrícula; cuadrícula-plantilla-columnas: repetir (3, 1fr); cuadrícula-plantilla-filas: repetir (2, 1fr); cuadrícula-columna-brecha: 60px; cuadrícula-fila-brecha: 30px; }

La cuadrícula final se veía así:

Ventajas:

  • La interfaz es fácil de usar y los colores están bien elegidos, lo que convierte a CSS Grid Generator en una excelente herramienta para los principiantes que desean familiarizarse más con las cuadrículas CSS.
  • CSS Grid Generator puede ayudarlo a obtener el resultado que desea para la mayoría de los casos de uso porque puede especificar la cantidad de columnas, filas y espacios en sus cuadrículas
  • Simplemente presione un botón para obtener una vista previa del código y copiarlo en su portapapeles

Contras:

  • No hay una plantilla que pueda elegir para ahorrarle tiempo
  • No podrás generar diseños complicados

2. Generador de diseño CSS

Podría haber puesto el Generador de diseño CSS primero en la lista. Si está buscando generar cuadrículas complicadas todo el tiempo, esta es probablemente la que debería marcar. Desarrollado por Braid Design System , CSS Layout Generator ofrece una amplia gama de opciones que resolverán la mayoría de los dolores de cabeza.

En mi trabajo diario, uso mucho las plantillas CSS Layout Generator porque te permiten elegir convenientemente entre una estructura con una barra lateral/contenedor o un encabezado/principal/pie de página.

<section class="layout">
  <!-- The left sidebar where you can put your navigation items etc. -->
  <div class="sidebar">1</div>

  <!-- The main content of your website -->
  <div class="body">2</div>
</section>

<style>
.layout {
  width: 1366px;
  height: 768px;
  display: grid;
  /* This is the most important part where we define the size of our sidebar and body  */
  grid:
    "sidebar body" 1fr
    / auto 1fr;
  gap: 8px;
}

.sidebar {
  grid-area: sidebar;
}

.body {
  grid-area: body;
}
</style>

La opción de la barra lateral se ve así:

Ventajas:

  • CSS Layout Generator le permite elegir entre seis plantillas estándar para comenzar más rápido
  • Hay muchas opciones para resolver casi todos los casos de uso
  • Puede cambiar entre cuadrículas y Flexbox, lo cual es útil para comparar ambas opciones
  • La interfaz es excelente y fácil de usar.

Contras:

  • Debido a que ofrece tantas opciones, CSS Layout Generator puede resultar confuso para un principiante.

3. Diseño de cuadrícula

Grid Layout fue desarrollado por Leniolabs y es otro generador de grillas que viene con muchas opciones. El código está disponible públicamente en GitHub si está interesado en contribuir .

La semana pasada, un cliente me pidió que diseñara una interfaz para mostrar métricas importantes sobre su producto (algo similar a Geckoboard ). El diseño que quería era muy preciso pero, gracias a LayoutIt, generé el código en unos segundos.

<div class="container">
  <div class="metric-1"></div>
  <div class="metric-2"></div>
  <div class="metrics-3"></div>
  <div class="metric-4"></div>
  <div class="metric-5"></div>
  <div class="metric-6"></div>
</div>

<style>
.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  gap: 20px 20px;
  grid-auto-flow: row;
  grid-template-areas:
    "metric-1 metric-1 metric-2"
    "metrics-3 metric-4 metric-2"
    "metric-5 metric-5 metric-6";
}
.metric-1 {
  grid-area: metric-1;
}
.metric-2 {
  grid-area: metric-2;
}
.metrics-3 {
  grid-area: metrics-3;
}
.metric-4 {
  grid-area: metric-4;
}
.metric-5 {
  grid-area: metric-5;
}
.metric-6 {
  grid-area: metric-6;
}
</style>

El diseño resultante se veía así:

Ventajas:

  • Grid Layout Es intuitivo de usar y ofrece muchas opciones
  • Puede configurar sus columnas y sus filas usando píxeles (px), fraccionarios (fr) y porcentajes (%)
  • Sus diseños se pueden exportar a CodePen, CodeSandbox o StackBlitz con un solo clic
  • La interfaz está bien diseñada, con un contraste adecuado entre las opciones y la vista previa de la cuadrícula.
  • Diseño de cuadrícula Admite opciones de ubicación de cuadrícula

Contras:

  • Este generador no proporciona plantillas para ahorrarle tiempo, que es la razón principal por la que lo puse tercero en la lista.

4. cuadrícula

En mi experiencia pasada, pasé mucho tiempo usando Griddy . Es un poco menos fácil de usar que la cuadrícula CSS creada por Sarah Drasner, pero ofrece más opciones.

Por ejemplo, le permite generar fácilmente una cuadrícula de cuatro columnas con tres filas:

.container {
  display: grid;
  grid-template-columns: 1fr 300px 1fr 1fr;
  grid-template-rows: 2fr 100px 1fr;
  grid-column-gap: 10px
  grid-row-gap: 20px
  justify-items: stretch
  align-items: stretch
}

El diseño resultante se ve así:

Ventajas:

  • Puede configurar sus columnas y sus filas usando píxeles (px), fraccionarios (fr) y porcentajes (%)
  • Las opciones proporcionadas son suficientes para resolver la mayoría de los casos de uso y probar diferentes alineaciones. En pocas palabras, hace el trabajo

Contras:

  • Puede que sea una cuestión de gustos, pero la barra lateral con las opciones no es la mejor interfaz para mí. Tienes que desplazarte un rato para conseguir lo que buscas
  • No hay plantillas para elegir
  • no hay minmax()funcion

5. Cssgr.id

Cssgr.id es otra excelente opción si está buscando un generador de cuadrícula que no tenga demasiadas opciones pero sí las suficientes para resolver la mayoría de los casos de uso.

Usé Cssgr.id el año pasado para crear una galería porque recordé que tenía una plantilla de galería. Con unos pocos clics, pude obtener algo bastante parecido a lo que necesitaba.

<div class="grid">
  <!-- This item will take 3 columns and 2 rows -->
  <div class="span-col-3 span-row-2">Item 1</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 2</div>
  <div class="span-row-2">Item 3</div>
  <div class="span-row-3">Item 4</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 5</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 6</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 7</div>

  <!-- This item will take 3 columns and 2 rows -->
  <div class="span-col-3 span-row-2">Item 8</div>

  <!-- This item will take 2 columns and 3 rows -->
  <div class="span-col-2 span-row-2">Item 9</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 10</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 11</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 12</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 13</div>

  <!-- This item will take 1 column and 1 row -->
  <div>Item 14</div>
</div>

<style>
.grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-gap: 10px;
}

/* Items with this class will take 3 columns */
.span-col-3 {
  grid-column: span 3 / auto;
}

/* Items with this class will take 2 columns */
.span-col-2 {
  grid-column: span 2 / auto;
}

/* Items with this class will take 2 rows */
.span-row-2 {
  grid-row: span 2 / auto;
}

/* Items with this class will take 3 rows */
.span-row-3 {
  grid-row: span 3 / auto;
}
</style>

La galería quedó así:

Ventajas:

  • Cssgr.id viene con cinco diseños de inicio prácticos para elegir (3 × 3, formación de fútbol, ​​encabezado/pie de página, galería y sitio web genérico)
  • Puede agregar texto de marcador de posición para ver cómo se representa con algún contenido escrito
  • Tiene una interfaz bien diseñada que se puede configurar fácilmente.

Contras:

  • No es el generador de grillas con más opciones

6. Cuadrícula CSS de Angry Tools

Angry Tools CSS Grid es el último generador de cuadrículas CSS de nuestra lista. Puede ser útil, aunque probablemente menos fácil de usar que las otras herramientas destacadas en esta guía.

Angry Tools CSS Grid también es útil para generar galerías. Al hacer clic en los cuadrados, puede definir sus tamaños y sus direcciones (horizontal o verticalmente).

<div class="angry-grid">
  <div id="item-0">Item 0</div>
  <div id="item-1">Item 1</div>
  <div id="item-2">Item 2</div>
  <div id="item-3">Item 3</div>
  <div id="item-4">Item 4</div>
  <div id="item-5">Item 5</div>
  <div id="item-6">Item 6</div>
  <div id="item-7">Item 7</div>
  <div id="item-8">Item 8</div>
  <div id="item-9">Item 9</div>
</div>

<style>
.angry-grid {
  display: grid;
  /* Our grid will be displayed using 3 rows */
  grid-template-rows: 1fr 1fr 1fr;
  /* Our grid will be displayed using 4 columns */
  grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
  /* You can define a gap between your columns and your rows if you need to */
  gap: 0px;
  height: 100%;
}

/* This grid item will start at row 1 and column 4 and end at row 2 and column 5 */
#item-0 {
  background-color: #8bf7ba;
  grid-row-start: 1;
  grid-column-start: 4;
  grid-row-end: 2;
  grid-column-end: 5;
}

/* This grid item will start at row 2 and column 3 and end at row 3 and column 5 */
#item-1 {
  background-color: #bf9aa7;
  grid-row-start: 2;
  grid-column-start: 3;
  grid-row-end: 3;
  grid-column-end: 5;
}

/* This grid item will start at row 2 and column 2 and end at row 3 and column 3 */
#item-2 {
  background-color: #c7656e;
  grid-row-start: 2;
  grid-column-start: 2;
  grid-row-end: 3;
  grid-column-end: 3;
}

/* This grid item will start at row 1 and column 1 and end at row 2 and column 3 */
#item-3 {
  background-color: #b659df;
  grid-row-start: 1;
  grid-column-start: 1;
  grid-row-end: 2;
  grid-column-end: 3;
}

/* This grid item will start at row 3 and column 1 and end at row 4 and column 3 */
#item-4 {
  background-color: #be6b5e;
  grid-row-start: 3;
  grid-column-start: 1;
  grid-row-end: 4;
  grid-column-end: 3;
}

/* This grid item will start at row 3 and column 4 and end at row 4 and column 6 */
#item-5 {
  background-color: #5bb9d7;
  grid-row-start: 3;
  grid-column-start: 4;
  grid-row-end: 4;
  grid-column-end: 6;
}

/* This grid item will start at row 1 and column 5 and end at row 3 and column 6 */
#item-6 {
  background-color: #56adba;
  grid-row-start: 1;
  grid-column-start: 5;
  grid-row-end: 3;
  grid-column-end: 6;
}

/* This grid item will start at row 1 and column 3 and end at row 2 and column 4 */
#item-7 {
  background-color: #9cab58;
  grid-row-start: 1;
  grid-column-start: 3;
  grid-row-end: 2;
  grid-column-end: 4;
}

/* This grid item will start at row 3 and column 3 and end at row 4 and column 4 */
#item-8 {
  background-color: #8558ad;
  grid-row-start: 3;
  grid-column-start: 3;
  grid-row-end: 4;
  grid-column-end: 4;
}

/* This grid item will start at row 2 and column 1 and end at row 3 and column 2 */
#item-9 {
  background-color: #96b576;
  grid-row-start: 2;
  grid-column-start: 1;
  grid-row-end: 3;
  grid-column-end: 2;
}
</style>

La galería resultante se ve así:

Ventajas:

  • Angry Tools CSS Grid viene con algunas plantillas entre las que puede elegir

Contras:

  • No tiene el mejor diseño en general. Para ser honesto, es bastante feo y puede ser difícil de usar.
  • No recomendaría esta herramienta para principiantes. Los desarrolladores avanzados probablemente también deberían elegir CSS Layout Generator o Grid LayoutIt en su lugar
  • Tienes que desplazarte para obtener los resultados de CSS

BONIFICACIÓN: hoja de trucos de cuadrícula CSS

Los generadores de cuadrículas CSS son excelentes cuando no está familiarizado con las propiedades CSS. Pero, a medida que se convierte en un desarrollador más avanzado, es posible que una hoja de trucos rápidos sea probablemente más útil.

😇 Si te puede ayudar, aquí está el que he hecho para mí:

gapEstablece el tamaño del espacio entre las filas y las columnas. Es una forma abreviada de las siguientes propiedades: row-gapycolumn-gap
row-gapEspecifica el espacio entre las filas de la cuadrícula.
column-gapEspecifica el espacio entre las columnas.
gridUna propiedad abreviada para: grid-template-rows, grid-template-columns, grid-template-areas, grid-auto-rows, grid-auto-columns,grid-auto-flow
grid-areaEspecifica el tamaño y la ubicación de un elemento de cuadrícula en un diseño de cuadrícula y es una propiedad abreviada para las siguientes propiedades: grid-row-start, grid-column-start, grid-row-end,grid-column-end
grid-auto-columnsEstablece el tamaño de las columnas en un contenedor de cuadrícula.
grid-auto-flowControla cómo se insertan en la cuadrícula los elementos colocados automáticamente
grid-auto-rowsEstablece el tamaño de las filas en un contenedor de cuadrícula
grid-columnEspecifica el tamaño y la ubicación de un elemento de cuadrícula en un diseño de cuadrícula y es una propiedad abreviada para las siguientes propiedades: grid-column-start,grid-column-end
grid-column-endDefine cuántas columnas abarcará un elemento o en qué línea de columna terminará el elemento
grid-column-gapDefine el tamaño del espacio entre las columnas en un diseño de cuadrícula
grid-column-startDefine en qué línea de columna comenzará el elemento
grid-gapDefine el tamaño del espacio entre filas y columnas en un diseño de cuadrícula y es una propiedad abreviada para las siguientes propiedades: grid-row-gap,grid-column-gap
grid-rowEspecifica el tamaño y la ubicación de un elemento de cuadrícula en un diseño de cuadrícula y es una propiedad abreviada para las siguientes propiedades: grid-row-start,grid-row-end
grid-row-endDefine cuántas filas abarcará un elemento o en qué línea de fila terminará el elemento
grid-row-gapDefine el tamaño del espacio entre las filas en un diseño de cuadrícula
grid-row-startDefine en qué línea de fila comenzará el artículo
grid-templateUna propiedad abreviada para las siguientes propiedades: grid-template-rows, grid-template-columns,grid-template-areas
grid-template-areasEspecifica áreas dentro del diseño de cuadrícula.
grid-template-columnsEspecifica el número (y el ancho) de las columnas en un diseño de cuadrícula
grid-template-rowsEspecifica el número (y las alturas) de las filas en un diseño de cuadrícula

Espero que esta comparación rápida de los mejores generadores de grillas CSS te haya ayudado a marcar tu favorito.

Además, si puedo darte un consejo crítico cuando trabajes con grillas CSS: tómate tu tiempo. Estos generadores son una excelente opción porque pueden ayudarlo a obtener los diseños que necesita paso a paso y evitar depender de una solución complicada.

¡Gracias por leer!  

Fuente: https://blog.logrocket.com/comparing-best-css-grid-generators/

#css 

Google's Flutter 1.20 stable announced with new features - Navoki

Flutter Google cross-platform UI framework has released a new version 1.20 stable.

Flutter is Google’s UI framework to make apps for Android, iOS, Web, Windows, Mac, Linux, and Fuchsia OS. Since the last 2 years, the flutter Framework has already achieved popularity among mobile developers to develop Android and iOS apps. In the last few releases, Flutter also added the support of making web applications and desktop applications.

Last month they introduced the support of the Linux desktop app that can be distributed through Canonical Snap Store(Snapcraft), this enables the developers to publish there Linux desktop app for their users and publish on Snap Store.  If you want to learn how to Publish Flutter Desktop app in Snap Store that here is the tutorial.

Flutter 1.20 Framework is built on Google’s made Dart programming language that is a cross-platform language providing native performance, new UI widgets, and other more features for the developer usage.

Here are the few key points of this release:

Performance improvements for Flutter and Dart

In this release, they have got multiple performance improvements in the Dart language itself. A new improvement is to reduce the app size in the release versions of the app. Another performance improvement is to reduce junk in the display of app animation by using the warm-up phase.

sksl_warm-up

If your app is junk information during the first run then the Skia Shading Language shader provides for pre-compilation as part of your app’s build. This can speed it up by more than 2x.

Added a better support of mouse cursors for web and desktop flutter app,. Now many widgets will show cursor on top of them or you can specify the type of supported cursor you want.

Autofill for mobile text fields

Autofill was already supported in native applications now its been added to the Flutter SDK. Now prefilled information stored by your OS can be used for autofill in the application. This feature will be available soon on the flutter web.

flutter_autofill

A new widget for interaction

InteractiveViewer is a new widget design for common interactions in your app like pan, zoom drag and drop for resizing the widget. Informations on this you can check more on this API documentation where you can try this widget on the DartPad. In this release, drag-drop has more features added like you can know precisely where the drop happened and get the position.

Updated Material Slider, RangeSlider, TimePicker, and DatePicker

In this new release, there are many pre-existing widgets that were updated to match the latest material guidelines, these updates include better interaction with Slider and RangeSliderDatePicker with support for date range and time picker with the new style.

flutter_DatePicker

New pubspec.yaml format

Other than these widget updates there is some update within the project also like in pubspec.yaml file format. If you are a flutter plugin publisher then your old pubspec.yaml  is no longer supported to publish a plugin as the older format does not specify for which platform plugin you are making. All existing plugin will continue to work with flutter apps but you should make a plugin update as soon as possible.

Preview of embedded Dart DevTools in Visual Studio Code

Visual Studio code flutter extension got an update in this release. You get a preview of new features where you can analyze that Dev tools in your coding workspace. Enable this feature in your vs code by _dart.previewEmbeddedDevTools_setting. Dart DevTools menu you can choose your favorite page embed on your code workspace.

Network tracking

The updated the Dev tools comes with the network page that enables network profiling. You can track the timings and other information like status and content type of your** network calls** within your app. You can also monitor gRPC traffic.

Generate type-safe platform channels for platform interop

Pigeon is a command-line tool that will generate types of safe platform channels without adding additional dependencies. With this instead of manually matching method strings on platform channel and serializing arguments, you can invoke native class and pass nonprimitive data objects by directly calling the Dartmethod.

There is still a long list of updates in the new version of Flutter 1.2 that we cannot cover in this blog. You can get more details you can visit the official site to know more. Also, you can subscribe to the Navoki newsletter to get updates on these features and upcoming new updates and lessons. In upcoming new versions, we might see more new features and improvements.

You can get more free Flutter tutorials you can follow these courses:

#dart #developers #flutter #app developed #dart devtools in visual studio code #firebase local emulator suite in flutter #flutter autofill #flutter date picker #flutter desktop linux app build and publish on snapcraft store #flutter pigeon #flutter range slider #flutter slider #flutter time picker #flutter tutorial #flutter widget #google flutter #linux #navoki #pubspec format #setup flutter desktop on windows

Lawrence  Lesch

Lawrence Lesch

1664370906

JavaScript, SCSS Helpers for Rendering High-resolution Image Variants

retina.js

JavaScript, Sass, Less, and Stylus helpers for rendering high-resolution image variants

retina.js makes it easy to serve high-resolution images to devices with displays that support them. You can prepare images for as many levels of pixel density as you want and let retina.js dynamically serve the right image to the user.

How it works

There are 4 ways to use retina.js:

  1. Automatically swapping out src paths on img tags.
  2. Automatically swapping out background image URLs in inline styles.
  3. Manually specifying the location of a high-res image variant (works for src attributes and inline styles).
  4. Automatically creating media queries for CSS background images.

Img Tags

retina.js assumes you are using Apple's prescribed high-resolution modifiers (@2x, @3x, etc) to denote high-res image variants on your server. It also assumes that if you have prepared a variant for a given high-res environment, that you have also prepared variants for each environment below it. For example, if you have prepared 3x variants, retina.js will assume that you have also prepared 2x variants.

With this in mind, you'll specify your highest environment level with the data-rjs attribute and let retina.js take it from there.

Let's say you have an image on your page that looks like this:

<img src="/images/my_image.png" data-rjs="3" />

In this case, we've set our resolution cap at "3", denoting that we've prepared 3x and 2x image variants. When the page loads, retina.js will check the actual resolution of the device environment to decide whether it should really serve up a 3x image. If the user happens to be in a 2x environment, retina.js will serve up the 2x image instead, assuming it will find the image at /images/my_image@2x.png.

If the environment does have 3x capabilities, retina.js will serve up the 3x image. It will expect that url to be /images/my_image@3x.png. If the environment has the ability to display images at higher densities than 3x, retina.js will serve up the image of the highest resolution that you've provided, in this case 3x.

Inline Styles

Previous versions of retina.js were unable to target background images set via inline styles. Now, if you apply a data-rjs attribute to any kind of element other than an img, the script will target inline background images instead of src attributes.

So if you created an element like this:

<div style="background: url(/images/my_image.png)" data-rjs="3"></div>

retina.js would convert it to something like this:

<div style="background: url(/images/my_image@3x.png)" data-rjs="3"></div>

The logic behind image swapping is exactly the same when dealing with background images as it is when dealing with src attributes. If the user's environment only supports 2x variants, retina.js will load the 2x variant instead of the 3x.

Note that it is up to you in a case like this to correctly apply background sizing and any other necessary background-related styles to the element. retina.js will not affect these.

Manually Specifying a High-Res URL

In previous versions, you could tell the script where to find your high-res file by using the data-at2x attribute. Now, if you pass a URL to the data-rjs attribute, retina.js will use the image at the path you specify for all high-resolution environments instead of trying to dynamically serve an auto-suffixed image path based on the environment's capabilities. This will work for both src attributes on img tags and inline background images on all other tags.

For example, you might write something like this:

<img
  src="/images/my_image.png"
  data-rjs="/images/2x/my-image.png" />

<!-- or -->

<div
  style="background: url(/images/my_image.png)"
  data-rjs="/images/2x/my-image.png">
</div>

If the user then loads the page in any kind of high-resolution environment, they'll get the following:

<img
  src="/images/2x/my-image.png"
  data-rjs="/images/2x/my-image.png" />

<!-- or -->

<div
  style="background: url(/images/2x/my-image.png)"
  data-rjs="/images/2x/my-image.png">
</div>

Media Queries

retina.js comes with mixins for SCSS, Sass, Less, and Stylus. These mixins work similarly to the JavaScript version in that they will dynamically serve images for as many high-res environments as you've prepared image variants for. Previously, these mixins were named "at2x" but because they now serve images for multiple environments, they have been renamed "retina".

In each language, the retina mixin allows 4 parameters:

  1. path - The path to your standard resolution image.
  2. cap - Optional. The highest resolution level for which you have prepared images. Defaults to 2.
  3. size- Optional. A value to be applied to the background-size property. Defaults to auto auto.
  4. extras- Optional. Any other values to be added to the background property. Defaults to nothing.

Here is an example wherein we are specifying that we have prepared images for both 2x and 3x environments:

SCSS

#item {
  @include retina('/images/my_image.png', 3, cover, center center no-repeat);
}

Sass

#item
  +retina('/images/my_image.png', 3, cover, center center no-repeat)

Less

#item {
  .retina('/images/my_image.png', 3, cover, center center no-repeat);
}

Stylus

#item
  retina('/images/my_image.png', 3, cover, center center no-repeat)

Regardless of the dialect, the output is effectively the same:

#item {
  background: url("/images/my_image.png") center center no-repeat;
  background-size: cover;
}

@media all and (-webkit-min-device-pixel-ratio: 1.5),
       all and (-o-min-device-pixel-ratio: 3 / 2),
       all and (min--moz-device-pixel-ratio: 1.5),
       all and (min-device-pixel-ratio: 1.5) {
  #item {
    background: url("/images/my_image@2x.png") center center no-repeat;
    background-size: cover;
  }
}

@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
  #item {
    background: url("/images/my_image@2x.png") center center no-repeat;
    background-size: cover;
  }
}

@media (-webkit-min-device-pixel-ratio: 3), (min-resolution: 288dpi) {
  #item {
    background: url("/images/my_image@3x.png") center center no-repeat;
    background-size: cover;
  }
}

Compatibility

retina.js is compatible with all modern browsers and should not throw errors in old browsers all the way back through IE6.

Installing & Launching

JavaScript

There are 2 ways to use the JavaScript version of retina.js:

  1. The old-school way (manually dropping the script into an html file).
  2. The new-school way (importing it into a larger JavaScript build process).

Old-School

To use retina.js the old-school way, download retina.min.js and put it on your server. Then, include the script in your html file at the bottom of your template, before your closing </body> tag.

<script type="text/javascript" src="/scripts/retina.min.js"></script>

Using this technique, retina.js will run automatically on page load. It will also create a globally available function called retinajs. Whenever you'd like to manually re-initialize the script, simply call window.retinajs().

If you don't pass any arguments to the retinajs function, it will only attempt to process images that have not previously been processed by the script. Optionally, you can pass a collection of HTML elements to the script, in which case it will only attempt to process elements in that collection, specifically the ones that have not been processed before. Your collection may take the form of an Array, NodeList, or jQuery selection.

retinajs();
// Finds all images not previously processed and processes them.

retinajs( [img, img, img] );
// Only attempts to process the images in the collection.

retinajs( $('img') );
// Same.

retinajs( document.querySelectorAll('img') );
// Same.

New-School

To use retina.js the new-school way, you'll want to require it (or import it if you're using ES6) into your Gulp/Webpack/Grunt/CommonJS/etc application. In this case, the script won't run automatically. Instead, it'll let you determine when you'd like it to run.

import retina from 'retina';

window.addEventListener('load', retina);

Notice that the retina function can be called as often as you need in order to re-initialize the image swapping.

If you don't pass any arguments to the retina function, it will only attempt to process images that have not previously been processed by the script. Optionally, you can pass a collection of HTML elements to the script, in which case it will only attempt to process elements in that collection, specifically the ones that have not been processed before. Your collection may take the form of an Array, NodeList, or jQuery selection.

retina();
// Finds all images not previously processed and processes them.

retina( [img, img, img] );
// Only attempts to process the images in the collection.

retina( $('img') );
// Same.

retina( document.querySelectorAll('img') );
// Same.

CSS Preprocessors

The process for including the CSS mixins is relatively straightforward. Here is a breakdown for each:

SCSS

Add the @mixin retina( ... ) mixin from _retina.scss to your SCSS stylesheet (or reference it in an @import). In your stylesheet, call the mixin using @include retina( ... ) anywhere instead of using background or background-image.

Sass

Add the =retina( ... ) mixin from _retina.sass to your Sass stylesheet (or reference it in an @import). In your stylesheet, call the mixin using +retina( ... ) anywhere instead of using background or background-image.

Less

Add the .retina( ... ) mixin from retina.less to your Less stylesheet (or reference it in an @import). In your stylesheet, call the mixin using .retina( ... ) anywhere instead of using background or background-image.

Stylus

Add the retina( ... ) mixin from retina.styl to your Stylus stylesheet (or reference it in an @import). In your stylesheet, call the mixin using retina( ... ) anywhere instead of using background or background-image.

Considerations for Ruby on Rails 3+

...or any framework that embeds some digest/hash to the asset URLs based on the contents, e.g. /images/image-{hash1}.jpg.

The problem with this is that the high-resolution version would have a different hash, and would not conform to the usual pattern, i.e. /images/image@2x-{hash2}.jpg. So automatic detection would fail because retina.js would check the existence of /images/image-{hash1}@2x.jpg.

There's no way for retina.js to know beforehand what the high-resolution image's hash would be without some sort of help from the server side. So in this case, there are a couple of options for handling it:

Bypass Digesting

One potential method is to bypass digesting altogether by implementing a process like team-umlaut's asset compile rake file which will generate non-digested asset files as necessary.

Use Manual Paths

Although it's not quite as fancy as dynamically serving up files based on the resolution of the user's environment, this may be a good time to pass a URL string to the data-rjs attribute so that you can manually tell retina.js exactly where to look for a high-resolution variant of your image.

Download Details:

Author: Strues
Source Code: https://github.com/strues/retinajs 
License: MIT license

#javascript #scss #sass #image